У меня проблемы с объявлением неполной структуры внутри специализации класса и последующим ее определением.
struct Foo {
template <bool Y, typename D>
struct Bar {};
template <typename D>
struct Bar<true, D> {
struct Qux;
};
template <typename D>
struct Bar<true, D>::Qux { int x; };
};
Этот код работает в gcc, но не работает в clang 3.3:
r.cpp:42:26: error: non-friend class member 'Qux' cannot have a qualified name
struct Bar<true, D>::Qux { int x; };
~~~~~~~~~~~~~~^
Если код написан в области имен (без struct Foo
), он работает в Clang тоже.
С другой стороны, если struct Foo
превращается в шаблон, как показано ниже, код ломается в gcc-4.9 (не выпущен), хотя он продолжает работать в gcc-4.7.
template <typename X>
struct Foo {
template <bool Y, typename D>
struct Bar {};
template <typename D>
struct Bar<true, D> {
struct Qux;
};
template <typename D>
struct Bar<true, D>::Qux { int x; };
};
Clang терпит неудачу с:
r.cpp:43:26: error: template specialization or definition requires a template parameter list corresponding to the nested type 'Bar<true, type-parameter-1-0>'
struct Bar<true, D>::Qux { int x; };
^
r.cpp:43:26: error: non-friend class member 'Qux' cannot have a qualified name
struct Bar<true, D>::Qux { int x; };
~~~~~~~~~~~~~~^
2 errors generated.
Сбой Gcc-4.9 с похожей ошибкой:
r.cpp:43:26: error: too few template-parameter-lists
struct Bar<true, D>::Qux { int x; };
^
Похоже, у вас нет выбора, кроме как поместить это определение в область пространства имен (или внутри Bar
). Параграф 9/1 (n3337) говорит, что ваш код является незаконным:
Если -Имя-руководитель класса содержит вложенное имя-специфический эр, Класс-специфический эр будет ссылаться на класс, который был
ранее объявленный непосредственно в классе или пространстве имен, к которому относится вложенное имя-специфический эр относится или в
элемент встроенного набора пространств имен (7.3.1) этого пространства имен (т.е. не просто унаследованный или введенный
используя декларирование), а также Класс-специфический эр должен появиться в пространстве имен, включающем предыдущую декларацию.
В таких случаях вложенное имя-специфический эр из -Имя-руководитель класса определения не должны начинаться с
decltype-специфический эр.
struct Foo {
template <bool Y, typename D>
struct Bar {};
};
template <typename D>
struct Foo::Bar<true, D> {
struct Qux;
};
template <typename D>
struct Foo::Bar<true, D>::Qux {
int x;
};