2009-07-01 27 views
9

¿Alguien sabe por qué las declaraciones de uso no parecen funcionar para importar nombres de tipos de clases base dependientes? Funcionan para las variables y funciones de los miembros, pero al menos en GCC 4.3, parecen ignorarse para los tipos.Accediendo a tipos de clases base dependientes

template <class T> 
struct Base 
{ 
    typedef T value_type; 
}; 

template <class T> 
struct Derived : Base<T> 
{ 
    // Version 1: error on conforming compilers 
    value_type get(); 

    // Version 2: OK, but unwieldy for repeated references 
    typename Base<T>::value_type get(); 

    // Version 3: OK, but unwieldy for many types or deep inheritance 
    typedef typename Base<T>::value_type value_type; 
    value_type get(); 

    // Version 4: why doesn't this work? 
    using typename Base<T>::value_type; 
    value_type get(); // GCC: `value_type' is not a type 
}; 

que tienen una clase base con un conjunto de typedefs de estilo asignador que me gustaría heredar lo largo de varios niveles de herencia. La mejor solución que he encontrado hasta ahora es la versión 3 anterior, pero tengo curiosidad de por qué la versión 4 no parece funcionar. GCC acepta la declaración de uso, pero parece ignorarla.

He comprobado el C++ Standard, C++ Prog. Lang. 3ª ed. [Stroustrup] y Plantillas C++ [Vandevoorde, Josuttis], pero ninguna parece abordar si las declaraciones de uso se pueden aplicar a tipos de clases base dependientes.

En caso de que ayude ver otro ejemplo, here is the same question being asked, pero no realmente respondido, en la lista de correo de GCC. El asker indica que ha visto 'using typename' en otro lugar, pero que GCC no parece apoyarlo. No tengo otro compilador compatible disponible para probarlo.

+0

Publique un código que debe compilar (en su opinión) para compilar los compiladores, pero no lo hace. Y publica cómo estás usando la plantilla. –

+0

Creo que toda la información relevante está arriba. Las versiones 1-4 funcionan en MSVC 9, que tiene una resolución de nombre de una etapa no conforme (es decir, en tiempo de instanciación). Solo las versiones 2 y 3 funcionan en GCC 4.3. No sé por qué razón la Versión 4 no debería ser válida, pero GCC no la aceptará. En cuanto al uso, realmente no importa cómo se crea una instancia. Solo estoy tratando de compilar la declaración de la plantilla. El código anterior es una simplificación de un adaptador de contenedor mucho más complejo. –

+0

Al publicar código aquí, no espere que las personas tengan que editarlo para compilarlo. –

Respuesta

8

Como Richard Corden señala, esta cuestión se abordó en el C++ Standard Core Language Defect Reports después fue ratificada la norma 2003: How do the keywords typename/template interact with using-declarations?

Propuesta de acuerdo (abril de 2003, revisado en octubre de 2003):

Añadir un nuevo párrafo a la parte inferior de 7.3.3 [namespace.udecl]:

Si una declaración usando-utiliza la palabra clave nombretipo y especifica una nombre dependiente (14.7.2 [temp.dep]), el nombre introducido por la using-declaration se trata como un typedef-name (7.1.3 [dcl.typedef]).

no parece este texto aparezca en la norma segunda edición del 15 de octubre de 2003.

GCC aún no implementa esta resolución, como se explica en bug 14258:

- ----- Comentario # 3 de Giovanni Bajo 2004-02-27 12:47 [respuesta] ------- El problema es que nuestro USING_DECL no registra el "nombre de tipo", que es el hecho de que es un tipo que es importado a través de él. Esto solía funcionar gracias a la extensión implícita del nombre de tipo , creo.

Duplicate bug 21484 indica que 'using typename' funciona en los compiladores Comeau e Intel. Como MSVC trata a todos los nombres como dependientes, el constructo es innecesario (pero permitido) para ese compilador.


Fixed en GCC 4.7 el 13 de diciembre de 2011!

+1

Este es un error, pero solo hace relativamente poco tiempo, así que creo que no deberías ser demasiado duro con gcc. El siguiente tema central resalta el cambio de redacción "http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#11". Esto entró en el estándar C++ '03. –

+0

Gracias, Richard, ¡ese es el enlace exacto que estaba buscando! –

-1

No incluyó un especificador de acceso (público/protegido/privado) en la plantilla para Base antes de declarar el typedef para Base :: value_type. Como resultado, el valor predeterminado es privado y no es accesible en las clases derivadas de Base.

+5

Ha definido sus tipos Base/Derivados como estructuras, por lo que sus miembros son * públicos * por defecto, no privados. – luke

Cuestiones relacionadas