This question介绍了C ++模板代码中需要typename
和template
消歧器的时间和原因。
在C ++ 03中不需要使用这些歧义器是否有效?在C ++ 11中怎么样?
答案 0 :(得分: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.
}