Pregunta

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 B recibo un error de que Vec_t no es reconocido y necesito escribirlo explícitamente?

typename A<T>::Vec_t v;
¿Fue útil?

Solución

Creo que esta pregunta es duplicada, pero no puedo encontrarla ahora. C ++ Standard dice que debe calificar completamente el nombre de acuerdo con 14.6.2 / 3:

  

En la definición de una plantilla de clase o un 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 la clase base no se examina durante la búsqueda de nombre no calificado ya sea en el punto de definición de la plantilla de clase o miembro o durante una instanciación de la plantilla de clase o miembro.

UPD: finalmente encontré duplicados: aquí está .

Otros consejos

Hay algo llamado nombres dependientes y no dependientes en el caso de plantillas.

Si el nombre depende del parámetro de plantilla T, su nombre dependiente y otros que no dependen del parámetro T son nombres independientes .

  

Aquí está la regla: el compilador no   mirar en clases base dependientes (como   A) al buscar personas no dependientes   nombres (como Vec_t). Como resultado,   el compilador no sabe que ni siquiera   existen y mucho menos son tipos.

El compilador no puede asumir que Vec_t es un tipo hasta que sepa 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 pases por este https://isocpp.org/ wiki / faq / templates # tipos de búsqueda de nombres no dependientes .

Enlace antiguo (roto): http: // www. parashift.com/c++-faq-lite/templates.html#faq-35.18

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.

en particular

Para completar, así es como podría mitigar un poco esta molestia:

  • vuelva a escribirdef esos tipos en clases derivadas, o mejor, como con métodos -
  • simplemente importe esos nombres en el ámbito de clase derivado con un using declaration:

template<typename T>
class A
{
public:
    typedef std::vector<T> Vec_t;
};


template<typename T>
class B : public A<T>
{
public:
    using typename A<T>::Vec_t;
    // .........

private:
    Vec_t v;
};

Puede ser útil si tiene más de una mención de la typedef heredada en la clase derivada. Además, no necesita agregar typename cada vez con esto.

Debe calificar explícitamente el uso de Vec_t porque el compilador no sabe de dónde proviene <=>.

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 <=> que no es un typedef, o incluso puede no incluir un miembro <=> en absoluto.

Vec_t no es un nombre dependiente, y el compilador necesita saber qué es 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 se instancia, ya que el nombre no depende del argumento de plantilla T (hasta donde el compilador puede asumir).

En general, typedefs en una clase base de plantilla parece bastante inútil para usar en una clase derivada. Sin embargo, los typedefs son útiles para el usuario.

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 utilizar un tipo de miembro público Vec_t de template <typename T> class A, debe declararlo explícitamente como

A<T>::Vec_t v;
OR
A<int>::Vec_t int_type;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top