c++ - Propagándose ''typedef'' a partir de la clase derivada para ''template''
templates inheritance (6)
Estoy tratando de definir la clase base, que contiene solo typedef.
template<typename T>
class A
{
public:
typedef std::vector<T> Vec_t;
};
template<typename T>
class B : public A<T>
{
private:
Vec_t v; // fails - Vec_t is not recognized
};
¿Por qué en BI recibo un error de que Vec_t no es reconocido y necesito escribirlo explícitamente?
typename A<T>::Vec_t v;
Creo que esta pregunta está duplicada, pero no puedo encontrarla ahora. El Estándar C ++ dice que debes calificar completamente el nombre de acuerdo con 14.6.2 / 3:
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 alcance 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.
UPD: encontré duplicado finalmente: aquí está .
Este concepto puede asociarse con la forma en que usamos std::vector<T>
. Por ejemplo, si tenemos un std::vector<int> Foo
. Ahora, decidimos usar cualquiera de sus tipos de miembros, digamos un iterator
. En este escenario, mencionamos explícitamente
std::vector<int>::iterator foo_iterator;
De manera similar, en su caso, para usar un miembro público escriba Vec_t
de la template <typename T> class A
, necesita declararlo explícitamente como
A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;
Hay algo llamado nombres dependientes y no dependientes en el caso de las plantillas.
Si el nombre depende del parámetro de la plantilla T, su nombre dependiente y otros que no dependen del parámetro T son nombres independientes .
Aquí está la regla: el compilador no busca en las clases base dependientes (como A) cuando busca nombres no dependientes (como Vec_t). Como resultado, el compilador no sabe que existen, y mucho menos son tipos.
El compilador no puede asumir que Vec_t
es un tipo hasta que conoce T
porque existe una especialización potencial de A<T>
donde A<T>:: Vec_t
es un miembro de datos
Entonces la solución es usar typename
typename A<T>::Vec_t v; ← good
Te recomiendo que revises este https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types .
Enlace antiguo (roto): http://www.parashift.com/c++-faq-lite/templates.html#faq-35.18
Necesita calificar explícitamente el uso de Vec_t
porque el compilador no sabe de dónde viene Vec_t
.
No puede asumir nada sobre la estructura de A, ya que la plantilla de clase A puede estar especializada. La especialización puede incluir un Vec_t
que no sea un typedef, o puede que ni siquiera incluya un miembro Vec_t
en absoluto.
Porque el compilador no está seguro de que Vec_t
nombre un tipo. Por ejemplo, A<T>
podría estar especializado para que T=int
no tenga ese typedef
particular.
Vec_t no es un nombre dependiente, y el compilador necesita saber de qué se trata sin instanciar ninguna plantilla (clase base en este caso). Realmente no es diferente de:
template <class T>
class X
{
std::string s;
}
Aquí también el compilador necesita saber acerca de std :: string incluso si X no está instanciado, ya que el nombre no depende del argumento de la plantilla T (en la medida que el compilador pueda suponer).
Con todo, los typedefs en una clase base de plantilla parecen bastante inútiles para su uso en la clase derivada. Sin embargo, los typedefs son útiles para el usuario.