Мне вложили шаблон класса в другом шаблоне. Частично специализация его легка: Я просто объявляю другого template< … >
блок в его родителе.
Однако мне нужна другая частичная специализация, которая, оказывается, определяет все ее локальные аргументы шаблона. Это превращает его в явную специализацию. Явные специализации, по любой причине, должны быть в объеме пространства имен. Для объявления этого вне его родительского класса родитель должен быть назначен, который требует непустого списка аргумента шаблона. Это подразумевает частичную специализацию. Частичная специализация - то, что я делаю, и она, как предполагается, работает в произвольном внешнем объеме. Но и GCC и Comeau не удается определить шаблонный параметр в родительском назначении с частичной специализацией формальные аргументы.
template< class X > struct A {
template< class Y > struct B; // initial declaration OK
template< class Z >
struct B< A< Z > > {}; // partial OK as long as there's a local arg
template<> // ERROR: this syntax triggers explicit specialization
struct B< int > {};
};
template<> // ERROR: can't nest template<>s here (why?)
template< class X > // ERROR: can't deduce X from type of A<X>::B<int> (why?)
struct A< X >::B< int > {};
(Я оставил весь свой нерабочий код внутри; прокомментируйте это соответственно, чтобы попытаться иметь смысл.)
Это незаконно в соответствии со стандартом C ++ 14.7.3 / 18:
.... объявление не должно явно определять член класса шаблон, если его включающие шаблоны классов не являются явно специализированными также.
Я не слишком часто использую вложенные классы. Моя основная жалоба заключается в том, что они имеют тенденцию к раздуванию кода класса, в который они вложены.
Поэтому я бы предложил другой обходной путь:
namespace detail
{
template <class X, class Z> class BImpl;
template <class X, class Z> class BImpl<X, A<Z> > {};
template <class X> class BImpl<X,int> {};
}
template <class X>
class A
{
template <class Z> struct B: BImpl<X,Z> {};
};
Просто обратите внимание, что он требует передачи X в качестве аргумента в BImpl
, если вы когда-нибудь захотите также специализироваться на A
. Забавно, что в этом случае я получаю только частичную специализацию!
По крайней мере, это работает в ВК 2010. Но я не могу написать def. of fun() для "int" вне объявления класса. EDIT: К сожалению, в g++ тоже есть проблемы с компиляциями. EDIT: Нижеприведенный код работал в VC 2010.
template<typename X>
class A
{
public:
A()
{
}
template<typename Y>
struct B
{
void fun();
};
template<>
struct B<int>
{
void fun()
{
cout << "Specialized version called\n";
}
//void fun();
};
public:
B<X> b;
};
template<typename X>
template<typename Y>
void A<X>::B<Y>::fun()
{
cout << "templated version called\n";
}
int main()
{
A<int> a;
a.b.fun();
A<float> a1;
a1.b.fun();
}
Сложный материал. Ваш начальный код ICE VC10 Beta2, хорошо.
Во-первых, я думаю, у вас есть это наоборот:
template<>
template< class X >
struct A< X >::B< int > {};
X - это параметр шаблона для структуры A, а B - полностью специализированный, поэтому я думаю, что это должно быть так:
template< class X >
template<>
struct A< X >::B< int > {};
Но даже это не компилируется . Тем не менее, текст ошибки действительно полезен:
a.cpp a.cpp (11): error C3212: 'A :: B': явный специализация члена шаблона должен быть членом явного специализация a.cpp (8): см. объявление 'A :: B'
Похоже, что полностью специализировать B разрешено только в том случае, если вы также полностью специализируете A.
Edit : Хорошо, я получил ответ от кого-то, кто может авторитетно высказаться по этому поводу - перефразируя, это очень темная область в стандарте, и это открытый вопрос для Комитета C ++, чтобы очистить его («это» является явной специализацией членов шаблонов классов). В ближайшей перспективе совет: «Не делай этого».