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

Why is §5/5 applied when deducing template arguments? Couldn't the rules be different?

本文关键字:规则 不能不 应用 参数 为什么      更新时间:2023-10-16

考虑以下示例:

#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&t具有int const&类型。

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

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

关于基本原理,让我们首先考虑为什么const没有进入参数类型演绎:

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-限定被忽略了。到函数的类型。这样的实例化可以产生非常不同的效果。那会很乱的。

然后,关于为什么删除引用,如果不是,那么这个程序,

#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输出不同顺序的数字。

但事实并非如此。

这是因为引用的设计使得在c++ 03中,a1int的引用,与直接是inta1是无法区分的。


对于基本原理的更明确和更有见地的观点(上面的观点非常合理,但仍然只是我的想法),可能是Bjarne stroustrup的《c++的设计和演变》。书里有些东西。与否。可惜我没有那本书。