2010-12-28 11 views
20
struct Bar { 
    enum { Special = 4 }; 
}; 

template<class T, int K> struct Foo {}; 
template<class T> struct Foo<T,T::Special> {}; 

Uso:¿Es posible especializar una plantilla usando una enumeración de miembro?

Foo<Bar> aa; 

falla al compilar con gcc 4.1.2 Se queja sobre el uso de T::Special para specilization parcial de Foo. Si Special fuera una clase, la solución sería un nombre tipo delante de ella. ¿Hay algo equivalente para él en enumeraciones (o enteros)?

+6

Una pregunta interesante. –

+0

Si reemplaza T :: Special con un entero concreto (99, por ejemplo), aún no compila bajo g ++ 4.4.0: 'número incorrecto de argumentos de plantilla (1, debería ser 2)'. Me doy cuenta de que esto es un cuestión separada, pero ¿el compilador no debería aceptar esto? – TonyK

Respuesta

9

El tipo de un argumento de plantilla sin tipo no puede depender de un parámetro de plantilla de una especialización parcial.

ISO C++ 03 14.5.4/9 dice

Una expresión argumento que no es de tipo parcialmente especializado no debe afectar a un parámetro de plantilla de la especialización parcial excepto cuando la expresión argumento es un identificador simple.

template <int I, int J> struct A {}; 
template <int I> struct A<I+5, I*2> {}; //error 
template <int I, int J> struct B {}; 
template <int I> struct B<I, I> {};  //OK 

Así que algo como esto es ilegal porque template<class T> struct Foo<T,T::Special> {};T::Special depende de T

El uso también es ilegal. Ha proporcionado un argumento de plantilla, pero debe proporcionar dos.

+1

¿Por qué el tipo de parámetro de plantilla sin tipo depende del parámetro de plantilla de la especialización parcial aquí? El tipo sigue siendo 'int', ¿no? –

+0

Estoy hablando del argumento de la plantilla (no sobre el parámetro de la plantilla 'int K')' T :: Special' que depende de 'T'. –

+0

Ah. El tipo del argumento depende de 'T', el tipo del parámetro es' int'. –

16

Desde que no está permitido por C++ como explained por Prasoon, por lo que una solución alternativa sería utilizar EnumToType plantilla de clase, código

struct Bar { 
    enum { Special = 4 }; 
}; 

template<int e> 
struct EnumToType 
{ 
    static const int value = e; 
}; 

template<class T, class K> //note I changed from "int K" to "class K" 
struct Foo 
{}; 

template<class T> 
struct Foo<T, EnumToType<(int)T::Special> > 
{ 
    static const int enumValue = T::Special; 
}; 

muestra a Ideone: http://www.ideone.com/JPvZy


O, simplemente puede especializarse de esta manera (si resuelve su problema),

template<class T> struct Foo<T,Bar::Special> {}; 

//usage 
Foo<Bar, Bar::Special> f; 
+3

¡Muy buena solución! –

+1

Una buena solución de hecho. +1 de mi parte :) –

+0

@James y Prasoon: gracias por la apreciación :-) – Nawaz

Cuestiones relacionadas