En ocasiones he visto algunos mensajes de error realmente indescifrables escupidos gccal usar plantillas ... Específicamente, he tenido problemas en los que las declaraciones aparentemente correctas estaban causando errores de compilación muy extraños que desaparecieron mágicamente al prefijar la typenamepalabra clave al comienzo del declaración ... (Por ejemplo, la semana pasada, estaba declarando dos iteradores como miembros de otra clase con plantilla y tuve que hacer esto) ...
¿De qué trata la historia typename?

Respuestas:
La siguiente es la cita del libro de Josuttis:
fuente
typename(¡aunque no todos!).La publicación BLog de Stan Lippman sugiere: -
Entonces, básicamente, Stroustrup reutilizó la palabra clave de clase sin introducir una nueva palabra clave que luego se cambia en el estándar por las siguientes razones
Como el ejemplo dado
la gramática del lenguaje se malinterpreta
T::A *aObj;como una expresión aritmética, por lo que se introduce una nueva palabra clave llamadatypenamele indica al compilador que trate la declaración posterior como una declaración.
Por eso tenemos ambos
Puedes echar un vistazo a esta publicación , definitivamente te ayudará, solo la extraje todo lo que pude
fuente
typenamenecesaria una nueva palabra clave , si podía usar la palabra clave existenteclasspara el mismo propósito?typenamese hizo necesario solucionar el problema de análisis como se describe en la respuesta de Naveen citando a Josuttis. (No creo que insertar unaclassen este lugar hubiera funcionado). Solo después de que se aceptara la nueva palabra clave para este caso, también se permitía en las declaraciones de argumentos de plantilla (¿ o son definiciones? ), Porqueclasssiempre ha habido algo engañoso.Considera el código
Desafortunadamente, no se requiere que el compilador sea psíquico, y no sabe si T :: sometype terminará refiriéndose a un nombre de tipo o un miembro estático de T. Por lo tanto, uno usa
typenamepara decirlo:fuente
En algunas situaciones donde se refiere a un miembro de los llamados dependientes tipo (que significa "dependiente del parámetro de plantilla"), el compilador no siempre puede deducir inequívocamente el significado semántico de la construcción resultante, porque no sabe qué tipo de nombre es (es decir, si se trata de un nombre de un tipo, un nombre de un miembro de datos o un nombre de otra cosa). En casos como ese, debe desambiguar la situación diciéndole explícitamente al compilador que el nombre pertenece a un nombre de tipo definido como miembro de ese tipo dependiente.
Por ejemplo
En este ejemplo, la palabra clave es
typenamenecesaria para que el código se compile.Lo mismo sucede cuando desea hacer referencia a un miembro de plantilla de tipo dependiente, es decir, a un nombre que designa una plantilla. También debe ayudar al compilador utilizando la palabra clave
template, aunque se coloca de manera diferenteEn algunos casos puede ser necesario usar ambos
(si obtuve la sintaxis correctamente).
Por supuesto, otra función de la palabra clave
typenamese utilizará en las declaraciones de parámetros de plantilla.fuente
El secreto radica en el hecho de que una plantilla puede especializarse para algunos tipos. Esto significa que también puede definir la interfaz completamente diferente para varios tipos. Por ejemplo, puedes escribir:
Uno podría preguntarse por qué es esto útil y de hecho: eso realmente parece inútil. Pero tenga en cuenta que, por ejemplo,
std::vector<bool>elreferencetipo se ve completamente diferente al de otrosTs. Es cierto que no cambia el tipo dereferenceun tipo a algo diferente pero, sin embargo, podría suceder.Ahora, ¿qué sucede si escribe sus propias plantillas con esta
testplantilla? Algo como estoparece estar bien para ti porque esperas que
test<T>::ptrsea un tipo. Pero el compilador no lo sabe y, de hecho, incluso el estándar le aconseja que espere lo contrario,test<T>::ptrno es un tipo. Para decirle al compilador qué espera, debe agregar untypenameantes. La plantilla correcta se ve asíEn pocas palabras: debe agregar
typenameantes cada vez que use un tipo anidado de una plantilla en sus plantillas. (Por supuesto, solo si se usa un parámetro de plantilla de su plantilla para esa plantilla interna).fuente
Dos usos:
templatepalabra clave de argumento (en lugar declass)typenamepalabra clave le dice al compilador que un identificador es un tipo (en lugar de una variable miembro estática)fuente
Creo que todas las respuestas han mencionado que la
typenamepalabra clave se usa en dos casos diferentes:a) Al declarar un parámetro de tipo de plantilla. p.ej
Que no hay diferencia entre ellos y son EXACTAMENTE iguales.
b) Antes de usar un nombre de tipo dependiente anidado para una plantilla.
El hecho de no usar
typenameconduce a errores de análisis / compilación.Lo que quiero agregar al segundo caso, como se menciona en el libro de Scot Meyers Effective C ++ , es que hay una excepción de usar
typenameantes de un nombre de tipo dependiente anidado . La excepción es que si usa el nombre de tipo dependiente anidado como una clase base o en una lista de inicialización de miembros , no debe usartypenameallí:Nota: El uso
typenamepara el segundo caso (es decir, antes del nombre de tipo dependiente anidado) no es necesario desde C ++ 20.fuente
fuente