这个问题涵盖了C++模板代码中何时以及为什么需要typename
和template
消歧器。
在C++03中不需要这些消歧符的情况下使用这些消歧器有效吗?用C++11怎么样?
对于一些"有效"的定义,它在符合C++03/C++11编译器中是有效的
C++03 ISO/IEC 14882:2003§14.2.5:
[注意:与
typename
前缀的情况一样,template
前缀在非严格必要的情况下是允许的;即,当->
或.
左侧的表达式,或嵌套名称说明符不依赖于模板参数时。]
C++11 ISO/IEC 14882:2011§14.2.5:
[注意:与
typename
前缀的情况一样,template
前缀在非严格必要的情况下是允许的;即,当嵌套名称说明符或->
或.
左侧的表达式不依赖于模板参数时,或者该用法不出现在模板的范围内。-尾注]
请注意,当有问题的成员实际上不是模板时,您不能使用template
——您不允许对其撒谎。还要注意,对于typename
,类型必须是限定的类型(例如X::Y
,而不仅仅是X
)。C++11也更改了它,这样你就不必在模板的范围内,而C++03要求你在模板中。还要注意的是,编译器可能会在是否真的允许执行这一操作上有所不同。例如,在Clang下,这会在标志-Wc++11-extensions
下发出警告。
以下是一些例子,假设以下定义:
struct X {
typedef int Y;
template <typename T> static void foo();
static void bar();
template <typename T> static void baz(T);
};
在C++03和C++11:中都无效
template <typename T>
void foo() {
typename int z = 0; // int is not a qualified name.
X::template bar(); // X::bar is not a template.
X::template baz(z); // no template argument list.
}
在C++03中无效,在C++11中有效(但在我的Clang副本上产生警告):
void bar() {
typename X::Y z = 0; // not in the body of a template, so
X::template foo<int>(); // no possibility of dependent names.
}
在C++03和C++11:中都有效
template <typename T>
void baz() {
typename X::Y z = 0; // not a dependent name, so 'typename'
X::template foo<int>(); // isn't strictly necessary.
}