template - Sintaxis de C++ para la especialización explícita de una función de plantilla en una clase de plantilla?
tipos de plantillas en c++ (4)
Tengo un código que funciona en VC9 (Microsoft Visual C ++ 2008 SP1) pero no en GCC 4.2 (en Mac):
struct tag {};
template< typename T >
struct C
{
template< typename Tag >
void f( T ); // declaration only
template<>
inline void f< tag >( T ) {} // ERROR: explicit specialization in
}; // non-namespace scope ''structC<T>''
Entiendo que GCC quisiera que moviera mi especialización explícita fuera de la clase, pero no puedo entender la sintaxis. ¿Algunas ideas?
// the following is not correct syntax, what is?
template< typename T >
template<>
inline void C< T >::f< tag >( T ) {}
GCC está en claro, aquí. MSVC tiene una extensión no estándar que permite la especialización en clase. El estándar, sin embargo, dice:
14.7.3.2:
2. Se debe declarar una especialización explícita en el espacio de nombres del cual la plantilla es miembro, o, para las plantillas de miembros, en el espacio de nombres del cual la clase adjunta o la plantilla de clase adjunta es un miembro. Se debe declarar una especialización explícita de una función miembro, clase miembro o miembro de datos estáticos de una plantilla de clase en el espacio de nombres del que la plantilla de clase es miembro.
Además, no puedes especializar parcialmente una función. (Aunque no estoy seguro de los detalles en su caso, ese sería el golpe final).
Podrías hacer esto:
#include <iostream>
struct true_type {};
struct false_type {};
template <typename T, typename U>
struct is_same : false_type
{
static const bool value = false;
};
template <typename T>
struct is_same<T, T> : true_type
{
static const bool value = true;
};
struct tag1 {};
struct tag2 {};
template< typename T >
struct C
{
typedef T t_type;
template< typename Tag >
void foo( t_type pX)
{
foo_detail( pX, is_same<Tag, tag1>() );
}
private:
void foo_detail( t_type, const true_type& )
{
std::cout << "In tag1 version." << std::endl;
}
void foo_detail( t_type, const false_type& )
{
std::cout << "In not tag1 version." << std::endl;
}
};
int main(void)
{
C<int> c;
c.foo<tag1>(int());
c.foo<tag2>(int());
c.foo<double>(int());
}
Aunque esto es algo feo.
No puede especializar una función miembro sin especializar explícitamente la clase contenedora.
Sin embargo, lo que puede hacer son llamadas hacia adelante a una función miembro de tipo parcialmente especializado:
template<class T, class Tag>
struct helper {
static void f(T);
};
template<class T>
struct helper<T, tag1> {
static void f(T) {}
};
template<class T>
struct C {
// ...
template<class Tag>
void foo(T t) {
helper<T, Tag>::f(t);
}
};
Prueba esto:
template <> template<typename T> inline void C<T> :: foo<tag2>(T) {}
Sé que esto puede no satisfacerlo, pero no creo que no tenga una especialización encerrada dentro de una estructura no explícitamente especializada.
template<>
template<>
inline void C< tag1 >::foo< tag2 >( t_type ) {}