2011-03-15 20 views
8

suponga que tiene el códigoerror "parámetro de plantilla no válido" en Visual Studio, pero no GCC

template <template<class> class BaseType> 
class EST16 
    : public BaseType<int> 
{ 
public: 
    EST16(double d) 
    { 
    } 
}; 

template <class T> 
class SCEST 
{ 
    T y; 
}; 
typedef EST16<SCEST> EST16_SC; 
class Child 
    : public EST16_SC 
{ 
public: 
    Child() 
     : EST16_SC(1.0) 
    { 
    } 

}; 



class NotWorkingChild 
    : public EST16<SCEST> 
{ 
public: 
    NotWorkingChild() 
     : EST16<SCEST>(1.0) 
    { 
    } 

}; 



TEST(TemplateTest, TestInstantiate) 
{ 
    Child child; 
    NotWorkingChild notWorkingChild; 
} 

Infantil y NotWorkingChild sólo se diferencian por el typedef. En tanto GCC compile, en Visual Studio el constructor de NotWorkingChild produce el siguiente error:

2>..\..\..\src\itenav\test\SCKFErrorStateTest.cpp(43) : error C3200: 'SCEST<T>' : invalid template argument for template parameter 'BaseType', expected a class template 
2>  with 
2>  [ 
2>   T=int 
2>  ] 

Puede explicar por qué esto es así? ¿Hay una solución portátil mejor que el typedef?

Gracias!

+1

¿Ha escrito algún código que realmente ejemplifique y use las clases de plantilla? Con eso quiero decir en, por ejemplo, 'main'. Una cosa que podría estar sucediendo es que VCC prueba la creación de instancias al ver el 'typedef', mientras que GCC no se molesta hasta que realmente se use una de sus clases secundarias. Si eso es cierto, entonces también obtendrías errores en GCC, tan pronto como escribas código que use una de las plantillas de clase hija. – phooji

+0

Sí, lo hice. La macro TEST crea una prueba de Google que recibe llamadas de main(). – Philipp

+0

Lo siento, la macro 'TEST' estaba justo después de mi límite de desplazamiento, así que me lo perdí. No estoy al 100% de por qué esto falla, pero he publicado un enfoque alternativo a continuación que debería ser más portátil entre los compiladores. También es más legible, en mi humilde opinión :) – phooji

Respuesta

11

El mensaje de error se debe a NotWorkingChild deriva (indirectamente) de SCEST<int>, lo que hace SCEST dentro del alcance de NotWorkingChild se refiere a la clase SCEST<int>, en lugar de la plantilla. MSVC tiene razón al rechazar esto, y GCC4.5 debería rechazarlo también (GCC4.5 tiene una búsqueda de nombre de clase inyectada más correcta).

Aquí es una solución que podría funcionar para ambos compiladores

class NotWorkingChild 
    : public EST16<SCEST> 
{ 
public: 
    NotWorkingChild() 
     : EST16<::SCEST>(1.0) 
    { 
    } 

}; 

notar que utilizamos el operador de resolución de alcance y la necesidad de poner un espacio antes :: (el token <: de lo contrario sería tomado como un dígrafo).


Noticias de última hora: C++ 0x hará el trabajo por encima incluso si lo hace EST16<SCEST>. La razón es que dice que si el nombre de clase inyectado se pasa a un parámetro de plantilla de plantilla, el nombre de clase inyectado se trata como una plantilla, en lugar de como un tipo. Por lo tanto, para C++ 0x, GCC sería el compilador que lo haría correctamente.

+0

Parece que VS "14" CTP aún requiere el operador de resolución de alcance. –

2

Compila en VS si cambia el inicializador para simplemente referirse al nombre de la clase de plantilla, EST16. Es decir .:

class NotWorkingChild : public EST16<SCEST> 
{ 
public: 
    NotWorkingChild() 
     : EST16(1.0) 
    { 
    } 
}; 
+1

eso es correcto, pero estoy buscando una solución portátil y esto no se compila con GCC :-( – Philipp

Cuestiones relacionadas