La propagación de ‘typedef» de base a la clase derivada para la ‘plantilla’

Estoy tratando de definir la clase base, que contiene typedef solo.

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 la B, me aparece un error de que Vec_t no es reconocido y necesito escribir explícitamente?

typename A<T>::Vec_t v;
  • Duplicado exacto: stackoverflow.com/questions/1567730/…
  • Bueno, realmente no es un duplicado exacto desde el post que mencionas habla acerca de un método mientras este habla de un tipo.
  • typename Un::Vec_t v; está bien. No hay necesidad de <T> no
InformationsquelleAutor dimba | 2009-10-29

7 Kommentare

  1. 44

    Creo que esta pregunta es duplicado, pero ahora no la encuentro. El Estándar de C++ dice que debe calificar el nombre de acuerdo a 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 clase de plantilla depende de una plantilla de parámetros, base ámbito de la clase no es examinada durante incondicional en la búsqueda del nombre ya sea en el punto de la definición de la plantilla de clase o miembro o durante una instanciación de la clase de plantilla o de los miembros.

    UPD: he encontrado duplicado por último: aquí es.

    • Por el camino, siempre recordarme que tenía que ‘re-typedef’ todo… no es agradable, no es agradable en absoluto.
    • por cierto, usted no necesita todos los argumentos de plantilla y todos, cuando la clasificación. Debido a que la inyección de nombre de clase, basta con escribir typename B::Vec_t
    • Estoy tratando de hacerlo como usted dijo, pero estoy recibiendo errores si no me especificar los parámetros de la plantilla para B. B no es una clase, un espacio de nombres, o enumeración)
    • Yo estoy teniendo el mismo resultado de error, pero sólo en uno de mis plataformas, una de ellas con un mayor estándar de C++. Me pregunto si la necesidad de calificar totalmente cambiado en algún momento?
  2. 37

    Hay algo que se llama dependiente y no dependientes nombres en el caso de las plantillas.

    Si el nombre depende del parámetro de plantilla T su dependiente de la nombre y otros, aquellos que no dependen del parámetro T se independiente nombres.

    He aquí la regla: el compilador no
    buscar en dependiente de clases base (como
    A) cuando se esté buscando no dependientes
    nombres (como Vec_t). Como resultado,
    el compilador no sabe es que
    existen ni hablar de los tipos.

    Compilador no puede asumir que Vec_t es un tipo hasta que conoce T porque Existe una posibilidad de especialización de A<T> donde A<T>:: Vec_t es un miembro de datos

    Así que la solución es el uso de typename

     typename A<T>::Vec_t v;   good

    Te recomiendo ir a través de este https://isocpp.org/wiki/faq/templates#nondependent-name-lookup-types.

    De edad (roto) enlace: http://www.parashift.com/c++-faq-lite/plantillas.html#faq-35.18

    • La suya fue la única respuesta que parecía proporcionar una solución además de una explicación. Gracias.
    • El enlace está roto
    • Te ofrezco un +1 si me avise que usted ha corregido el enlace.
    • El enlace ha sido actualizado.
  3. 7

    Porque el compilador no es seguro que Vec_t el nombre de un tipo. Por ejemplo, A<T> podría ser especializado para T=int a no han particular typedef.

    • Para T una variable de tipo A<T> es meramente adelante declarado, no tiene una definición. Sólo A<t> donde t es un tipo (no de tipo variable) puede ser definido (por la especialización de una definición de plantilla o por un explícito de la especialización). IOW, incluso si se retira la plantilla explícita y parcial de las especialidades de C++ (y, pero no cambie nada), todavía no sería correcta.
  4. 5

    Para la integridad, aquí es cómo usted podría mitigar este problema molesto un poco, ya sea:

    • re-definiciones de los tipos en las clases derivadas, o mejor, como con
      métodos –
    • sólo importar los nombres en la clase derivada alcance 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 usted tiene más de una mención de que el heredado typedef en la clase derivada. También no es necesario agregar typename cada vez con esto.

    • Usted tiene una errata. using typename A::Vec_t; debe ser using typename A<T>::Vec_t;
  5. 2

    Usted necesita para calificar explícitamente el uso de Vec_t porque el compilador no sabe donde Vec_t viene.

    No podemos asumir nada acerca de la estructura de Una, ya que la plantilla de clase a puede ser especializado. La especialización puede incluir un Vec_t que no es un typedef, o puede incluso no incluir un miembro Vec_t a todos.

  6. 1

    Vec_t no es un dependiente de nombre, y el compilador necesita saber lo que es, sin crear instancias de cualquiera de las plantillas de base de la clase en este caso). Esto realmente no es muy diferente de:

    template <class T>
    class X
    {
        std::string s;
    }

    Aquí el compilador necesita saber acerca de std::string, incluso si X no está instanciado, ya que el nombre no depende de la plantilla argumento T (en la medida en que el compilador puede asumir).

    Con todo, las definiciones de tipos en una plantilla de base de la clase parecen bastante inútiles para su uso en la clase derivada. El typedefs son útiles para el usuario, sin embargo.

    • a qué te refieres class X : T { aquí?
  7. 1

    Este concepto puede estar asociada con la forma en que el uso de std::vector<T>. Por ejemplo, si tenemos un std::vector<int> Foo. Ahora, hemos decidido utilizar cualquiera de los tipos de miembros, digamos que un iterator. En este escenario nos menciona explícitamente

    std::vector<int>::iterator foo_iterator;

    De manera similar, en su caso, con el fin de utilizar un miembro del público, tipo de Vec_t de template <typename T> class A, debe declarar explícitamente como

    A<T>::Vec_t v;
    OR
    A<int>::Vec_t int_type;

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea