2012-02-14 22 views
10

Aquí está mi código:método de la plantilla de la especialización de clase de plantilla

template<typename T1, typename T2> class MyClass 
{ 
public: 
    template<int num> static int DoSomething(); 
}; 

template<typename T1, typename T2> template<int num> int MyClass<T1, T2>::DoSomething() 
{ 
    cout << "This is the common method" << endl; 
    cout << "sizeof(T1) = " << sizeof(T1) << endl; 
    cout << "sizeof(T2) = " << sizeof(T2) << endl; 
    return num; 
} 

Funciona bien. Pero cuando trato de agregar este

template<typename T1, typename T2> template<> int MyClass<T1, T2>::DoSomething<0>() 
{ 
    cout << "This is ZERO!!!" << endl; 
    cout << "sizeof(T1) = " << sizeof(T1) << endl; 
    cout << "sizeof(T2) = " << sizeof(T2) << endl; 
    return num; 
} 

recibo errores compiller: especialización inválida explícito antes «>» símbolo plantilla-id «HacerAlgo < 0>» para «int MyClass :: HacerAlgo()» no se coincide con cualquier declaración de plantilla

Uso g ++ 4.6.1 ¿Qué debo hacer?

Respuesta

7

Por desgracia, no se puede especializar una plantilla que es un miembro de una plantilla de clase, sin la plantilla especializada externa:

C++ 11 14.7.3/16: En una declaración explícita para una especialización miembro de una plantilla de clase o miembro que aparece en el ámbito de espacio de nombres, la plantilla miembro y algunas de sus plantillas de clase adjuntas pueden permanecer no especializadas, excepto que la declaración no debe especializar explícitamente una plantilla miembro de clase si sus plantillas de clases adjuntas no son explícitamente especializado también.

Creo que su mejor opción es agregar el parámetro adicional a MyClass, y luego especializarlo parcialmente.

+0

Pero el ejemplo no está explícitamente especializado en una plantilla de miembro de clase: está especializando una plantilla de miembro de función.Por lo tanto, la parte que ha resaltado no se aplica y el permiso otorgado en la parte anterior de la oración parece aplicarse. –

+2

@ AlanStokes: "plantilla de miembro de clase" significa una plantilla que es miembro de una clase; podría ser una plantilla para una función o una clase anidada. La "plantilla de clase de miembro" se referiría específicamente a una plantilla de clase que es miembro (según el uso de ese término en 14.7.3/1). GCC, al menos, usa esa interpretación. –

+0

14.5.2/1 sugiere que una plantilla que es miembro de una clase es simplemente una "plantilla de miembro". "plantilla de miembro de clase" no parece ser un término definido. Yuck. Pero parece que [DR 529] (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#529) aclarará esto para estar de acuerdo con su respuesta. –

0

Eso es triste pero cierto: no puede especializarse de forma explícita una plantilla de clase a menos que sus plantillas de clase encierra también son explícitamente especializada. Para más información puede leer

A continuación me he especializado MiClase primera y todo lo terminé.

#include <iostream> 
using namespace std; 

template<typename T1, typename T2> class MyClass 
{ 
public: 
    template<int num> static int DoSomething(); 
}; 

template<typename T1, typename T2> template<int num> int MyClass<T1, T2>::DoSomething() 
{ 
    cout << "This is the common method" << endl; 
    cout << "sizeof(T1) = " << sizeof(T1) << endl; 
    cout << "sizeof(T2) = " << sizeof(T2) << endl; 
    return num; 
} 

template<> template<> int MyClass<char, int>::DoSomething<0>() 
{ 
    cout << "This is ZERO!!!" << endl; 
    cout << "sizeof(T1) = " << sizeof(char) << endl; 
    cout << "sizeof(T2) = " << sizeof(int) << endl; 
    return 0; 
} 

int main() { 
    MyClass<char, int> m; 
    m.DoSomething<2>(); 
    m.DoSomething<0>(); 
    return 0; 
} 

Salida:

This is the common method 
sizeof(T1) = 1 
sizeof(T2) = 4 
This is ZERO!!! 
sizeof(T1) = 1 
sizeof(T2) = 4 

EUREKA! Esto funciona bien en MSVCPP 10.

#include <iostream> 
using namespace std; 

template<typename T1, typename T2> class MyClass 
{ 
public: 
    template<int num> static int DoSomething(); 
    template<> static int DoSomething<0>() { 
    cout << "This is ZERO!!!" << endl; 
    cout << "sizeof(T1) = " << sizeof(T1) << endl; 
    cout << "sizeof(T2) = " << sizeof(T2) << endl; 
    return 0; 
    } 
}; 

template<typename T1, typename T2> template<int num> int MyClass<T1, T2>::DoSomething() 
{ 
    cout << "This is the common method" << endl; 
    cout << "sizeof(T1) = " << sizeof(T1) << endl; 
    cout << "sizeof(T2) = " << sizeof(T2) << endl; 
    return num; 
} 

int main() { 
    MyClass<char, int> m; 
    m.DoSomething<2>(); 
    m.DoSomething<0>(); 
    return 0; 
} 

Salida:

This is the common method 
sizeof(T1) = 1 
sizeof(T2) = 4 
This is ZERO!!! 
sizeof(T1) = 1 
sizeof(T2) = 4 

Por cierto, ¿no return num; de la especialización. Nunca sabe qué es num.

+2

[No, no lo hace] (http://ideone.com/A5yTx) –

+0

@MikeSeymour Ok. Pero lo hace en MSVCPP 10. – DaddyM

+1

@DaddyM: MSVC no fuerza algunas de las reglas estándar. Especialmente con la programación de plantillas esto apesta. Siempre escribo las partes complicadas de la plantilla en MingW, si se compila y luego lo muevo a MSVC. –

Cuestiones relacionadas