2012-07-23 18 views
5

Tengo el siguiente código:especialización parcial en C++ 11

template<class T, int I=44> struct test {T j = I;}; 

template<int J> struct test<int, J> {int j = J;}; 

int main() 
{ 
    test<55> jj; 

    std::cout << jj.j << std::endl; 
    return(1); 
} 

El compilador (sonido metálico) se queja sólo alrededor de la línea test<55> jj

No entiendo por qué? Hay un trabajo alrededor?

Y si se queja de esa línea, ¿por qué no se queja de la segunda definición de plantilla?

Gracias de antemano.

El mensaje es:

enable.cpp:17:8: error: template argument for template type parameter must be a type 
test<55> jj; 
    ^~ 
enable.cpp:9:16: note: template parameter is declared here 
template<class T, int I=44> struct test 
+0

¿Podría vincular el mensaje de error? – Morwenn

Respuesta

6

El problema es que no ha entendido cómo funciona la selección de una especialización de plantilla de clase.

Su especialización:

template<int J> struct test<int, J> {int j = J;}; 

no crea una plantilla para el que sólo tiene que pasar en un solo parámetro de plantilla int.

test<55> jj; // doesn't work because there's no template<int J> struct test 

En cambio, lo que hace es crear una especialización de template<class T, int I> struct test que se utiliza cuando los argumentos de plantilla a template<class T, int I> struct test coinciden con la especialización, es decir test<int,J>.

test<int,55> jj; // uses the specialization template<int J> struct test<int, J> 

Aquí está la cita clave de la norma:

En un nombre de tipo que hace referencia a una especialización de plantilla de clase, (por ejemplo, A<int, int, 1>) la lista de argumentos debe coincidir con el parámetro de plantilla lista de la plantilla primaria. Los argumentos de la plantilla de una especialización se deducen de los argumentos de la plantilla primaria.[énfasis añadido]

                                                                                                                                                                      - 14.5.5.1 [temp.class.spec.match] p4


usted parece estar tratando de establecer int como tipo predeterminado para T mientras establece simultáneamente un valor predeterminado para I. Creo que su intención es poder especificar un tipo y un valor, especificar solo un tipo y obtener 44 como valor predeterminado, o especificar solo un valor y obtener int como un tipo predeterminado.

Desafortunadamente, no conozco una forma de especificar los valores predeterminados independientes de esa manera. Puede especificar los valores predeterminados (template<class T=int, int I=44> struct test) pero obtener el tipo predeterminado también requerirá aceptar el valor predeterminado.

Sin embargo, si usted está dispuesto a utilizar un segundo nombre, puede hacerlo:

template <int I> 
using test_int = test<int, I>; 

Esto crea una plantilla de alias tales que sólo tiene que especificar un valor:

test_int<55> jj; 

Y esto terminará usando cualquier especialización que test<int, I> pasa a resolver si hay una especialización explícita o si el compilador genera una implícita.

3

El primer error se produce porque el compilador intenta instanciar el parámetro primera plantilla (class T) con 55. Esto no funciona, ya que 55 no es un tipo en sí, pero una instancia de eso. Sin embargo, test<int> funciona porque aquí el parter de la plantilla es un tipo, como lo solicita la firma de su plantilla.

Lo que quiere en su lugar es "currying" para tipos, aka. aliasing plantilla:

template <typename T> 
struct test2 = using test<T, 55>; 

Aquí sólo tiene que proporcionar una T para elegir 55 como segundo parámetro fijo. Pero aún necesita usar ese tipo dándole un T concreto, por ejemplo, test2<double>.

Los comentarios indican que también podría estar interesado en la siguiente variante:

template <int I> 
using test3 = test<int, I>; 

Aquí fijar el primer parámetro de tipo int, que le permite usarlo como lo hizo en su código:

test3<55> t; 
+0

Hay tantas cosas mal en el código ... En primer lugar, la sintaxis obviamente falla. Segundo, él no quiere especificar el tipo. En tercer lugar, eso no es una especialización parcial. – Xeo

+3

La especialización corrige T a int, y usa 55 solo como el valor que está usando. Probablemente esté buscando 'template usando test_int = test ;' en su lugar. – bames53

+0

El alias de plantilla en la respuesta es equivalente a un valor predeterminado, que no es lo que el usuario realmente quiere. –

Cuestiones relacionadas