I have a class template nested inside another template. Partially specializing it is easy: I just declare another template< … >
block inside its parent.
I tend not to use nested classes too much. My main complaint is that they have a tendency to bloat the code of the class they are nested in.
I would therefore propose another workaround:
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> {};
};
Just note that it requires to pass X as an argument to BImpl
if ever you wish to also specialize A
. Funny thing is that in this case, I end up with only partial specialization!
Atleast this works in VC 2010. But, I am unable to write the def. of fun() for "int" outside the class declaration. EDIT: Unfortunately g++ has also compilations issues. EDIT: The code below worked on 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();
}
It is illegal under C++ standard 14.7.3/18:
.... the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well.
Complex stuff. Your initial code ICE's VC10 Beta2, nice.
First off, I think you have this backwards:
template<>
template< class X >
struct A< X >::B< int > {};
X is a template param to struct A, and B is the one fully specialized, so I think it should be this:
template< class X >
template<>
struct A< X >::B< int > {};
But even this fails to compile. The error text is actually useful, though:
a.cpp a.cpp(11) : error C3212: 'A::B' : an explicit specialization of a template member must be a member of an explicit specialization a.cpp(8) : see declaration of 'A::B'
It looks like it is only legal to fully specialize B if you also fully specialize A.
Edit: Ok, I heard back from someone who can speak authoritatively on this - to paraphrase, this is a very murky area in the standard, and it's an open issue with the C++ Committee to clean it up ("it" being explicit specializations of members of class templates). In the near term, the advice is "Don't do that".