C++ 是";typename";C+中允许/要求+;11使用声明?

C++ 是";typename";C+中允许/要求+;11使用声明?,c++,c++11,typename,using-declaration,C++,C++11,Typename,Using Declaration,以下代码在g++和clang中正确编译: template<typename T> struct foo { class iterator; using bar = foo::iterator; }; int main() {} 然后三个编译器都成功地编译了它。原始版本正确吗?(即,这是MSVC错误还是gcc/clang扩展)[temp.res]/p3: 当限定id意指的类型不是 当前实例化(14.6.2.1)的成员及其 嵌套名称说明符是指依赖类型,它的前缀应为关

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

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

int main() {}
然后三个编译器都成功地编译了它。原始版本正确吗?(即,这是MSVC错误还是gcc/clang扩展)

[temp.res]/p3:

当限定id意指的类型不是 当前实例化(14.6.2.1)的成员及其 嵌套名称说明符是指依赖类型,它的前缀应为关键字
typename
,形成一个typename说明符

[临时部门类型]/p1:

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

  • 在类模板的定义中,类模板的嵌套类、类模板的成员或嵌套类的成员 对于类模板,类的注入类名(第9条) 模板或嵌套类
  • [……]
[临时部门类型]/p4:

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

  • 一种非限定名称,在查找时,它至少引用当前实例化类或非依赖类的一个成员 其基类。[注意:这只能在查找 类模板定义所包含的作用域中的名称。-结束 注]
  • 一种限定id,其中嵌套的名称说明符引用当前实例化,并且在查找时至少引用一个实例 当前实例化或非依赖的类的成员 其基类。[注:如果未找到此类成员,以及 当前实例化有任何依赖的基类,然后 限定id是未知专业化的成员;请参见下文。 -[完注]
  • [……]
foo
是当前的实例化
foo::iterator
是一个限定id,其中嵌套的名称说明符(
foo::
)引用当前实例化,当查找时,“引用作为当前实例化或其非依赖基类的类的至少一个成员”;因此,它是当前实例化的成员。因此,[temp.res]/p3不适用,不需要
typename
。您仍然可以添加一个-或直接使用
迭代器
不合格。

来自标准:

14.6.2.1相关类型[临时部门类型]

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

__在类模板、类模板的嵌套类、类模板的成员或类模板的嵌套类的成员的定义中,类模板的注入类名称(第9条) 或嵌套类

名称
foo
引用了当前的实例化,这是显而易见的

由于
iterator
在模板的定义中声明为嵌套类,
iterator
引用了
foo
当前实例化中的名称
foo::iterator
iterator
相同

using bar = foo::iterator;
以及

using bar = iterator;
应该有用


在我看来,您似乎遇到了MSVC缺陷。

允许,是的。必选,否。
foo::iterator
指定当前实例化的一个成员。我认为这可以做到,您发现它更快,+1:)
using bar = foo::iterator;
using bar = iterator;