模板别名如何影响模板参数推导

How do template aliases affect template parameter deduction?

本文关键字:参数 影响 别名 何影响      更新时间:2023-10-16

在C++03中,模板参数推导在某些上下文中不会发生。例如:

template <typename T> struct B {};
template <typename T>
struct A
{
    typedef B<T> type;
};
template <typename T>
void f(typename A<T>::type);
int main()
{
    B<int> b;
    f(b);  // ERROR: no match
}

这里,int不是为T推导的,因为诸如A<T>::type之类的嵌套类型是非推导上下文。

我是否写了这样的函数:

template <typename T> struct B {};
template <typename T>
void f(B<T>);
int main()
{
    B<int> b;
    f(b);
}

一切都很好,因为B<T>推导的上下文。

然而,在C++11中,模板别名可以用来伪装嵌套类型,语法类似于第二个例子。例如:

template <typename T> struct B {};
template <typename T>
struct A
{
    typedef B<T> type;
};
template <typename T>
using C = typename A<T>::type;
template <typename T>
void f(C<T>);
int main()
{
    B<int> b;
    f(b);
}

在这种情况下,模板参数推导会起作用吗?换句话说,模板别名是推导的上下文还是非推导的上下文?还是他们继承了他们别名的推断/非推断状态?

换句话说,模板别名是推导的上下文还是非推导的上下文?

在不使用模板别名的情况下,它们与等效代码一样具有可推导性。例如

template<typename T>
using ref = T&;
template<typename T>
void f(ref<T> r);

现在你可以调用f(x)T会被推导得非常好。在f的定义时,ref<T>已经被类型T&所取代。CCD_ 10是一个推导的上下文。

在您的情况下,C<T>typename A<T>::type替换,这是T的非推导上下文,因此无法推导T

想象一下:

template <typename T> struct Foo { typedef   T type; }
template <> struct Foo<char>     { typedef int type; }
template <typename T> using mytype = typename Foo<T>::type;
template <typename T> void f(mytype<T>);

现在,如果我想要int n; f(n);,我如何决定我是想要T = int还是T = char?不受模板别名影响的整个问题是,您无法将向后推导出所有可能定义某些内容的内容。

我认为C++标准中的相关引用是14.5.7[临时别名]第2段:

当模板id指的是别名模板的专用化时,它等效于通过将其模板参数替换为别名模板的类型id中的模板参数而获得的关联类型。[注:别名模板名称永远不会推导出来。--尾注]

引用后有一个例子,它有效地阐明了在函数模板中使用别名模板并希望推导模板参数是毫无意义的。这显然适用于不涉及嵌套类型的情况。