在C++ 11中使用声明是允许/需要"typename"吗?

M.M*_*M.M 12 c++ typename using-declaration c++11

以下代码在g ++和clang中正确编译:

template<typename T>
struct foo
{
    class iterator;
    using bar = foo::iterator;
};

int main() {}
Run Code Online (Sandbox Code Playgroud)

但MSVC 2013会出现以下错误:

foo.cpp(9): error C2061: syntax error : identifier 'iterator'
          foo.cpp(10) : see reference to class template instantiation 'foo<T>' being compiled
foo.cpp(9): error C2238: unexpected token(s) preceding ';'
Run Code Online (Sandbox Code Playgroud)

如果我将该行更改为:

using bar = typename foo::iterator;
Run Code Online (Sandbox Code Playgroud)

然后所有三个编译器都成功编译.原始版本是否正确?(即这是一个MSVC错误,还是一个gcc/clang扩展)

T.C*_*.C. 7

[temp.res]/P3:

qualified-id旨在引用不是当前实例化成员的类型(14.6.2.1)并且其 嵌套名称说明符引用依赖类型时,它应以关键字为前缀typename,形成typename -specifier.

[temp.dep.type]/P1:

名称是指当前实例化(如果是)

  • 在类模板的定义,类模板的嵌套类,类模板的成员或类模板的嵌套类的成员中,类模板的inject-class-name(第9节)或嵌套类
  • [...]

[temp.dep.type]/P4:

名称是当前实例化成员(如果是)

  • 一个非限定名称,在查找时,指的是当前实例化或其非依赖基类的类的至少一个成员.[ 注意:只有在类模板定义所包含的范围中查找名称时才会出现这种情况.- 结束说明 ]
  • 一个qualified-id,其中嵌套名称说明符引用当前实例化,并且在查找时,引用类的至少一个成员,该类是当前实例化或其非依赖基类.[ 注意:如果没有找到这样的成员,并且当前实例化具有任何依赖的基类,则qualified-id是未知专门化的成员; 见下文.- 结束说明 ]
  • [...]

foo是当前的实例化.foo::iterator是一个qualified-id,其中nested-name-specifier(foo::)引用当前实例化,当查找时,"引用类的至少一个成员,它是当前实例化或其非依赖基类" ; 因此它是当前实例化的成员.因此,[temp.res]/p3不适用,typename不需要.您仍然可以添加一个 - 或者直接使用iterator不合格.