Aquí hay un ejemplo de código que reproduce mi problema:
template class Base { public: Base() {} virtual ~Base() {} protected: int myOption; virtual void set() = 0; }; template class ChildClass : public Base < std::vector > { public: ChildClass() {} virtual ~ChildClass() {} protected: virtual void set(); }; template void ChildClass::set() { myOption = 10; }
Mi uso en main()
:
ChildClass myObject;
Me aparece el siguiente error (gcc 4.4.3 en ubuntu):
‘myOption’ no se declaró en este ámbito
Si mi ChildClass no tuviera un nuevo parámetro de plantilla, esto funcionaría bien, es decir:
class ChildClass : public Base < std::vector >
Pude resolverlo, si mi método set se ve así:
Base<std::vector >::myOption = 10;
Funciona bien. Aún así, no estoy seguro de por qué necesito especificar todos los parámetros de la plantilla.
myOption
no es un nombre dependiente, es decir, no depende explícitamente de los argumentos de la plantilla, por lo que el comstackdor intenta buscarlo antes. Debe hacer que sea un nombre dependiente:
template void ChildClass::set() { this->myOption = 10; }
Ahora depende del tipo de this
y, por lo tanto, de los argumentos de la plantilla. Por lo tanto, el comstackdor lo vinculará en el momento de la creación de instancias.
Esto se llama búsqueda de nombres en dos fases .
En la definición de una plantilla de clase o miembro de una plantilla de clase, si una clase base de la plantilla de clase depende de un parámetro de plantilla, el scope de clase base no se examina durante la búsqueda de nombres no calificados en el punto de definición de la clase plantilla o miembro o durante una instanciación de la plantilla o miembro de la clase.
El siguiente código debería funcionar.
template void ChildClass::set() { Base >::myOption = 10; }