在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);
}
在这种情况下模板参数推导会起作用吗?换句话说,模板别名是推导上下文还是非推导上下文?或者他们是否继承了别名的推断/非推断状态?
答案 0 :(得分:9)
换句话说,模板别名是推导的上下文还是非推导的上下文?
它们与等效代码一样可以在不使用模板别名的情况下进行推导。例如
template<typename T>
using ref = T&;
template<typename T>
void f(ref<T> r);
现在您可以致电f(x)
,T
将被完美地推断。在f
的定义时间,ref<T>
已被类型T&
取代。 T&
是推断的上下文。
在您的情况下,C<T>
被typename A<T>::type
取代,这是T
的非推断上下文,因此无法推断出T
。
答案 1 :(得分:1)
想象一下:
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
?整个问题不受模板别名的影响,因为您不能将向后推导到可能定义某些内容的所有内容。
答案 2 :(得分:1)
我认为C ++标准中的相关引用是14.5.7 [temp.alias]第2段:
当template-id引用别名模板的特化时,它等同于通过替换别名模板的type-id中的template-parameters的template-arguments获得的关联类型。 [注意:永远不会推断出别名模板名称。 - 结束说明]
引用后面有一个例子,它有效地说明在函数模板中使用别名模板并希望推导出模板参数是没有意义的。这显然适用于不涉及嵌套类型的情况。