2013-05-26 1 views
3

У меня возникают проблемы с определением внутреннего класса за пределами класса, в котором он объявлен.Двухуровневый класс C++ работает с GCC, но не работает с Clang

struct Base { 
    struct A { 
     struct B; 
    }; 
    struct A::B { 
    }; 
}; 

Он собирает и работает с GCC, но не на Clang с этой ошибкой:

innerclass.cpp:6:12: error: non-friend class member 'B' cannot have a qualified name 
    struct A::B { 
      ~~~^ 

Если внешний класс Base опущен код работает на Clang.

Нельзя ли таким образом определить внутренний класс? Если да, то как это сделать?

Платформа:
OS X 10.8.3
XCode 4.6.2
Clang компании Apple LLVM версии 4.2 (лязг-425.0.24) (на основе LLVM 3.2svn)
GCC GCC версии 4.2.1 (на основе на Apple Inc. build 5658) (LLVM build 2336.11.00)

ответ

5

Я боюсь, что GCC является разрешительным. Пункт 9/1 из C++ 11 Стандарт определяет, что класс-голова-имяявляется:

вложенное-имя-описатель (опция) Класс имя

Это означает полное имя может использоваться как имя класса. Кроме того, первая часть пункта 9/11 указывает:

If a class-head-name contains a nested-name-specifier, the class-specifier shall refer to a class that was previously declared directly in the class or namespace to which the nested-name-specifier refers, [...]

И вы действительно объявить класс B внутри класса A. Тем не менее, вторая часть этого же пункта добавляет:

[...] and the class-specifiershall appear in a namespace enclosing the previous declaration. In such cases, the nested-name-specifier of the class-head-name of the definition shall not begin with a decltype-specifier.

В вашем случае класса спецификаторstruct A::B { } делает не появляются в области видимости пространства имен, но в рамках одного класса (попробуйте изменить struct Base в namespace Base, и вы увидите, что Кланг принимает его).

Таким образом, правильный способ крепления это определить класс в области видимости пространства имен, а не внутри Base:

// ... 

struct Base::A::B 
{ 
};