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

时间:2012-04-02 22:18:01

标签: c++ templates c++11 typename

This question介绍了C ++模板代码中需要typenametemplate消歧器的时间和原因。

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

1 个答案:

答案 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.
}