There is a template class A
used in class hierarchy of B::C_#
which specialize method create()
of A
:
template <typename T>
class A
: public std::map<std::string, double (T::*)() const>
{
...
void create();
...
};
template <typename T>
void A<T>::create()
{ assert(false); }
One of these subclasses C_#
(let's say C_0
) was great until recently. Everything went fine until C_0
decided to become a template. He got everything going except this create()
specialization. It tries to specialize create()
the following way:
template<class N1, class N2>
class C_0: public B<N1, N2>
{
...
}
...
template<class N1, class N2>
some_namespace::A< some_namespace::C_0<N1, N2> >
some_namespace::C_0<N1, N2>::A_;
template <>
void some_namespace::A< C_0<N1, N2> >::create() // line 1151
{
blah_(&C_0<N1, N2>::get_stuff);
}
but C_0
's attempts so far failed:
C_0.h:1151:45: error: 'N1' was not declared in this scope
C_0.h:1151:49: error: 'N2' was not declared in this scope
C_0.h:1151:51: error: template argument 1 is invalid
C_0.h:1151:51: error: template argument 2 is invalid
C_0.h:1151:53: error: template argument 1 is invalid
C_0.h:1151:63: error: 'create' is not a template function
Please help poor creature to overcome his trouble.
Also tried to do template method specialization in specialized C_0
:
namespace some_namespace
{
class C_0_specialized: public C_0<double_t, size_t>
{};
template <>
void A<C_0_specialized>::create()
{
blah_(&C_0_specialized::get_stuff);
}
}
This time it compiles, but calls the original method, which is void A<T>::create() { assert(false); }
Solution
Ok, so I ended up doing partial specialization of the whole template class A
within C_0
template level with C_0
argument list:
template<class N1, class N2>
class A< C_0<N1, N2> >
{
...
void create()
{
blah_(&C_0<N1, N2>::get_stuff);
}
...
}
The reason is because: 1) partial specialization of template methods is not allowed, so it is not possible to specialize just void create()
and when class is partially specialized all methods and variables have to be re-defined in the specialization; 2) explicit specialization of template method void create()
is not possible within C_0
level because A
depends on C_0
template argument list; 3) Moving void create()
specialization to C_0_specialized
, where it could be explicitly specialized because at C_0_specialized
the template argument list is resolved, was not possible because the instance of A
(instantiated as A_
in the code above) is used within template C_0
and therefore A_
would not see the specialization of A
at C_0
level. That's why at that level it was calling the base version of void create()
. Also moving A_
to the level of C_0_specialized
was not possible due to too much overhead.
Good thing is the class A
is not big, but still it would be preferable to specialize only void create()
.
I found this resource very useful for explaining differences between explicit and partial specialization of templates.
N1
andN2
. It's your choice. – stefan