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

时间:2015-05-13 04:07:50

标签: c++ c++11 typename using-declaration

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

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

int main() {}

然而,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 ';'

如果我将该行更改为:

using bar = typename foo::iterator;

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

2 个答案:

答案 0 :(得分:7)

[temp.res] / P3:

  

qualified-id 旨在引用不是a的类型时   当前实例化的成员(14.6.2.1)及其成员    nested-name-specifier 是指依赖类型,它应以关键字typename作为前缀,形成 typename-specifier

[temp.dep.type] / P1:

  

名称是指当前实例化,如果它是

     
      
  • 在类模板的定义中,类模板的嵌套类,类模板的成员或嵌套类的成员   类模板,类的注入类名(第9节)   模板或嵌套类,
  •   
  • [...]
  •   

[temp.dep.type] / P4:

  

名称是当前实例化的成员,如果它是

     
      
  • 一个非限定名称,当查找时,指的是当前实例化或非依赖项的类的至少一个成员   基类。 [注意:这只能在查找时发生   由类模板定义包含的范围中的名称。 - 端   注意]
  •   
  • qualified-id ,其中嵌套名称说明符引用当前实例化,并且当查找时,指的是至少一个   作为当前实例化或非依赖类的类的成员   基类。 [注意:如果找不到这样的成员,那么   当前实例化有任何依赖的基类,然后是   qualified-id是未知专业化的成员;见下文。    - 结束记录]
  •   
  • [...]
  •   

foo是当前的实例化。 foo::iterator qualified-id ,其中嵌套名称说明符foo::)引用当前实例化,当查找时, &#34;指的是当前实例化或其非依赖基类的类的至少一个成员&#34 ;;因此它是当前实例化的成员。因此,[temp.res] / p3不适用,不需要typename。您仍然可以添加一个 - 或者直接使用iterator不合格。

答案 1 :(得分:2)

来自标准:

  

14.6.2.1依赖类型 [temp.dep.type]

     

1名称是指当前实例化,如果它是

     

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

名称foo指的是当前的实例化,这很明显。

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

using bar = foo::iterator;

以及

using bar = iterator;

应该有用。

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