2010-06-25 6 views
6

Estoy portando mi código de Windows de C++ (msvc & intel) a Linux (g ++). El código usa muchas plantillas (me gusta la metaprogramación ;-). Pero no puedo compilar este código:problema de plantilla de g ++

template <class TA> 
struct A 
{ 
    template <class TAB> struct B; 
}; 


template <class TC> 
struct C {}; 


template <class TD> 
struct D 
{ 
    template <class TTD> class T {}; 
}; 


template<class TA> 
    template<class TBA> 
struct A<TA>::B : C<typename D<TA>::T<TBA> > 
{ 
    int foo; 
}; 

g ++ me dice que en la definición de A :: B, clase C tiene argumentos de plantilla no válidos. ¡Pero en msvc e intel funciona bien! ¿Cuál es el problema aquí? PD: Lo siento, no puedo publicar el código original, porque es demasiado complicado. Pero este ejemplo es prácticamente el mismo y da el mismo error en g ++. Gracias.

ACTUALIZACIÓN: he encontrado que el problema está en el argumento TBA de T. g ++ no me gusta el uso de la segunda plantilla en la definición.

+0

que he visto que "la plantilla plantilla struct ..." sintaxis antes, pero nunca he sabe lo que significa o por qué es sintaxis legal. ¿Qué significa (cuando se menciona "plantilla" dos veces delante de una estructura así)? – Dennis

+1

@Dennis: es necesario para la definición de plantillas anidadas fuera de la plantilla adjunta, consulte p. Ej. [aquí] (http://www.comeaucomputing.com/techtalk/templates/#outsidedef). –

+0

TA es un argumento de plantilla de A, y TAB es un argumento de plantilla de A :: B – f0b0s

Respuesta

10

Usted necesita la palabra clave template

template<class TA> 
    template<class TBA> 
struct A<TA>::B : C<typename D<TA>::template T<TBA> > 
{ 
    int foo; 
}; 

GCC es correcta para dar un diagnóstico aquí. Esto se debe a que T no se puede buscar en el ámbito dependiente D<TA>. El significado de < depende de si T es una plantilla o no. El Estándar dice que se supone que T no es una plantilla y, por lo tanto, T no puede ser seguido por una lista de argumentos de plantilla.

template es como typename en que le dice al compilador para tratar T como plantilla y que el < es el comienzo de una lista de argumentos, en cualquier caso. La norma dice en los párrafos 14.2/2 y 14.2/4

Para un nombre de la plantilla para ser calificados explícitamente por los argumentos de plantilla, el nombre debe ser conocida para referirse a una plantilla.

Cuando aparece el nombre de una especialización de plantilla de miembro después. o -> en una expresión de postfijo, o después de especificador de nombre anidado en un id-calificado, y la expresión de postfijo o id-calificado depende explícitamente de un parámetro de plantilla (14.6.2), el nombre de la plantilla de miembro debe ser prefijado por la plantilla de la palabra clave. De lo contrario, se asume que el nombre no es una plantilla.

En su caso, usted tiene T aparecen después de que el anidado de nombre especificador D<TA> que depende de la plantilla de parámetros TA. Para que el especificador typename se analice correctamente, la construcción D<TA>::T<TBA> debe interpretar T como el nombre de una plantilla de clase, que 14.2 prohíbe.


En ese tema, siempre es una buena idea para tratar de compilar con Clang

main1.cpp:21:37: error: use 'template' keyword to treat 'T' as a dependent template name 
struct A<TA>::B : C<typename D<TA>::T<TBA> > 
            ^
            template 
1 error generated. 
+1

BRILLIANT, THANX! – f0b0s

+0

bien, lo tengo.No sé sobre la segunda palabra clave 'typename', pero ahora una 'plantilla'. – f0b0s

+0

Guau, realmente me gusta este mensaje de diagnóstico, ahora eso es lo que espera del compilador ideal. –

Cuestiones relacionadas