首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在推导模板参数时应用§5/5?规则就不能不同吗?

为什么在推导模板参数时应用§5/5?规则就不能不同吗?
EN

Stack Overflow用户
提问于 2014-07-18 15:34:56
回答 1查看 121关注 0票数 3

请考虑以下示例:

代码语言:javascript
复制
#include <iostream>

template<typename T>
void f(T t) {
    std::cout << t << '\n';
    static_assert(std::is_same<T, int const*>::value, "T != int const*");
    static_assert(std::is_same<decltype(t), int const*>::value, "decltype(t) != int const*");
}

template<typename T>
void g(T t) {
    std::cout << t << '\n';
    static_assert(std::is_same<T, int>::value, "T != int");
    static_assert(std::is_same<decltype(t), int>::value, "decltype(t) != int");
    t++;
}

int main()
{
    int x = 22;
    int const* px = &x;

    f(px);

    int const& rx = x;
    g(rx);
}

代码正常执行。但根据现行规则我们得到:

  • T == int const*t在调用f(px)中模板函数f的实例化中具有int const*类型。
  • T == intt在调用g(rx)中模板函数g的实例化中具有int类型。

我对第二个推论的第一个想法将是与指针情况对称的东西,即使用T == int const&和带有int const&类型的t

我想我知道编译器执行的当前演绎过程是怎么回事。根据第5.5节,引用将被删除在传递给rx的表达式g中。也就是说,用于参数推导的rx类型是int const。请注意,随着这一更改,const (在rx声明中是而不是顶层)变成了顶级const。然后,在第三个项目点(§14.8.2.1/2 )中,constint const类型中被忽略,因为它现在是顶级const

在我看来,这个计划似乎是相当人为的。因此,我在想,为什么第5/5节必须应用于一个用于推断模板参数的表达式?必须有一个更有力的理由来证明这条规则是合理的,我不知道。这就是我想知道的。谢谢。

EN

回答 1

Stack Overflow用户

发布于 2014-07-18 17:08:29

关于基本原理,让我们首先考虑为什么const不进行参数类型推断:

代码语言:javascript
复制
template< class Type >
void foo( Type v ) { v = 0; }

auto main() -> int
{
    int const x = 3;
    foo( x );
}

这很好地编译,因为C++11§14.8.2.1/2第三个破折号是这么说的,“对于类型的演绎,忽略了A类型的顶级cv-限定符”。

我猜这其中很大一部分的理由是,否则各种实际的参数cv限定都会产生完全相同的函数类型的函数模板实例化,因为形式参数的顶级cv限定被忽略了wrt。函数的类型。这样的实例化可以产生截然不同的效果。会很乱的。

那么,关于为什么删除引用,嗯,它们不是这个程序,

代码语言:javascript
复制
#if defined( USE_REF )
#   define Q &&
    auto kind = "ref";
#else
#   define Q
    auto kind = "non-ref";
#endif

template< class A1, class A2 >
void foo( A1 a1, A2 a2 )
{
    a1 ^= a2;
    a2 ^= a1;
    a1 ^= a2;
}

#include <iostream>
#include <typeinfo>
auto main() -> int
{
    using namespace std;
    int Q a1 = 111;
    int Q a2 = 222;
    foo( a1, a2 );
    cout << kind << ' ' << a1 << ' ' << a2 << endl;
}

会根据USE_REF的不同顺序输出数字吗?

但事实并非如此。

这是因为引用的设计使得a1 (在C++03中是对int的引用)与a1 (直接是int )是无法区分的。

对于更明确和更知情的基本观点(上面的观点非常可信,但仍然只是我对它的想法),的“C++的设计和进化”一书可能包含了一些东西。或者不是。不幸的是我没有那本书。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24828832

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档