在不需要时使用"template"和"typename"消歧器

HC4*_*ica 7 c++ templates typename c++11

这个问题涵盖了C++模板代码中何时以及为何需要使用typenametemplate消除歧义.

在C++ 03中不需要使用这些消歧器是否有效?在C++ 11中怎么样?

Joh*_*eek 11

它符合C++ 03/C++ 11编译器的有效性,适用于"有效"的定义.

C++ 03 ISO/IEC 14882:2003§14.2.5:

[ 注意:就像typename前缀的情况一样,在template不是绝对必要的情况下允许使用前缀; 即,当->or .或左侧的表达式或嵌套名称说明符不依赖于模板参数时.]

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);
};
Run Code Online (Sandbox Code Playgroud)

在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.
}
Run Code Online (Sandbox Code Playgroud)

在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.
}
Run Code Online (Sandbox Code Playgroud)

在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.
}
Run Code Online (Sandbox Code Playgroud)