c++ - ¿Por qué no se requiere `typename` para una clase base que es un tipo anidado?
templates inheritance (3)
Me sorprendió mucho ver que no es necesario agregar
typename
cuando aparece un tipo dependiente como una clase base:
struct B {};
struct wr
{ typedef B type; };
template<class T>
struct A : T::type
{};
int main()
{
A<wr> a;
(void)a;
}
¿Por qué no se requiere
typename
delante de
T::type
?
¿Por qué no se requiere
typename
delante deT::type
?
Porque no puedes heredar de un valor.
Utiliza
typename
para decirle al compilador que un identificador anidado dado es un tipo, pero para la herencia, ese debe ser el caso de todos modos para que pueda omitirlo; es por eso que el lenguaje proporciona una excepción al
typename
, regla para los especificadores de base.
De
cppreference
(énfasis mío):
El desambigador
typename
para nombres dependientesEn una declaración o definición de una plantilla, incluida la plantilla de alias, un nombre que no sea miembro de la instancia actual y que dependa de un parámetro de plantilla no se considera un tipo a menos que se use la palabra clave typename o a menos que ya sea establecido como un nombre de tipo , por ejemplo, con una declaración typedef o al usarse para nombrar una clase base .
Tenga en cuenta que obtendremos más lugares donde se puede omitir P0634 , consulte P0634 .
Es un caso especial, como otros señalaron. Para citar el estándar sobre esto:
[temp.res]
5 Se supone implícitamente que un nombre calificado usado como el nombre en un tipo de clase o decltype o un especificador de tipo elaborado nombra un tipo, sin el uso de la palabra clave typename. En un especificador de nombre anidado que contiene inmediatamente un especificador de nombre anidado que depende de un parámetro de plantilla, se supone implícitamente que el identificador o la identificación de plantilla simple nombran un tipo, sin el uso de la palabra clave typename. [Nota: la palabra clave typename no está permitida por la sintaxis de estas construcciones. - nota final]
Y en C ++ 20, habrá incluso más excepciones a la necesidad de
typename
.
Solo necesita usar
typename
si necesita decirle al compilador que espere un tipo en lugar de otra cosa.
Como solo se puede heredar un tipo, no hay ambigüedad, por lo que
typename
es superfluo.