2010-01-19 37 views
29

tengo código que funciona en VC9 (Microsoft Visual C++ 2008 SP1), pero no en GCC 4.2 (en Mac):sintaxis C++ para la especialización explícita de una función de plantilla en una clase de plantilla?

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 me gustaría pasar mi especialización explícita fuera de la clase, pero me no puede entender la sintaxis ¿Algunas ideas?

// the following is not correct syntax, what is? 
template< typename T > 
template<> 
inline void C<T>::f<tag>(T) {} 

Respuesta

26

No puede especializar una función de miembro sin especializar explícitamente la clase contenedora.
Lo que se puede hacer sin embargo es desviar las llamadas a una función miembro de un tipo parcialmente especializados:

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); 
    } 
}; 
+0

Esto es similar a la solución que estoy usando, ¡gracias! Me pregunto si hay una manera de hacer esto de forma menos veraz usando Boost. – jwfearn

+0

No realmente, no se vuelve más fácil en general. Necesita una función de ayuda para evitar el problema de * "la clase adjunta tiene que estar explícitamente especializada" * y necesita mover esa en una clase para hacer una especialización parcial. –

1

Prueba esto:

template <> template<typename T> inline void C<T> :: foo<tag2>(T) {} 
+0

pues no, que no funciona – jwfearn

+0

lo siento - Creo que he mezclado el orden de THW dos clasificados plantilla. Intenta colocar el que tiene los soportes vacíos a la izquierda. –

+0

nope nuevamente (error: no se permite la especialización parcial de la plantilla) 'foo jwfearn

0

Sé que esto no se puede satisfacer, pero no creo que puede que no tenga una especialización encerrado dentro de una estructura no explícitamente especializado.

template<> 
template<> 
inline void C<tag1>::foo<tag2>(t_type) {} 
8

GCC está en el 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. An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member. An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member.

Además, no puede especializar parcialmente una función. (Aunque estoy seguro acerca de los detalles de su caso, que sería el golpe final.)

Usted podría 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.

+4

Tal vez sea el estándar de C++ el que no está claro ... Si Microsoft puede hacerlo, ¿por qué los demás compiladores no pueden hacerlo? –

Cuestiones relacionadas