2011-03-13 17 views
16

Tengo la función GetContainer() de la siguiente manera.g ++ error de parámetro de plantilla

template<typename I,typename T,typename Container> 
Container& ObjCollection<I,T,Container>::GetContainer() 
{ 
    return mContainer; 
} 

Cuando utilizo este método de la siguiente manera

template<typename I,typename T> 
T& DynamicObjCollection<I,T>::Insert(T& t) 
{ 
    GetContainer().insert(&t); 
    return t; 
} 

llegué errores.

error: there are no arguments to ‘GetContainer’ that depend on a template parameter, 
so a declaration of ‘GetContainer’ must be available 

error: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of 
an undeclared name is deprecated) 

Funciona bien con MSVC, pero g ++ no es tan permisivo. ¿Qué pasa con el código?

+0

¿Se puede publicar un ejemplo completo y compilable que demuestre el problema? –

Respuesta

53

Me di cuenta de que la función GetContainer es un método de ObjCollection, mientras que Insert es miembro de DynamicObjectCollection. A partir de esto, voy a suponer que DynamicObjectCollection hereda de ObjectCollection.

Si este es realmente el caso, el problema es que cuando escribe una clase de plantilla que hereda de una clase base de plantilla, la forma en que funciona la búsqueda de nombres es ligeramente diferente de la búsqueda de nombres en clases normales. En particular, no puede simplemente hacer referencia a los miembros de la clase base usando sus nombres; necesita indicar al compilador dónde buscar el nombre. La razón por la que esto funciona en Visual Studio es que el compilador de Microsoft C++ en realidad tiene este comportamiento incorrecto y permite que el código que es técnicamente ilegal compile muy bien.

Si desea invocar la función GetContainer de la clase base, tiene dos opciones. En primer lugar, que de manera explícita se puede indicar que la llamada es una función miembro:

this->GetContainer().insert(&t); 

Ahora que el compilador sabe que GetContainer es miembro de DynamicObjectCollection, se sabe que podría tener que mirar hacia arriba GetContainer en la clase base, por lo que diferirá la búsqueda de nombres hasta que se cree una instancia de la plantilla.

La otra opción disponible sería añadir una declaración using en el cuerpo de la clase:

template <typename I, typename T> 
class DynamicObjectCollection: public ObjectCollection<I, T, /* ? */> { 
public: 
    using ObjectCollection<I, T, /* ? */>::GetContainer; 

    /* ... */ 
}; 

Esto también indica inequívocamente al compilador que GetContainer se puede definir en la clase base, y por lo que aplaza las operaciones de búsqueda hasta creación de instancias de plantilla.

Si esto no es aplicable a su situación, avíseme y puedo eliminar esta publicación.

Espero que esto ayude!

+5

+1 para escribir rápido – Erik

+1

¡Gracias! ahora funciona. – prosseek

Cuestiones relacionadas