Na ocasião, vi algumas mensagens de erro realmente indecifráveis serem exibidas gcc
ao usar modelos ... Especificamente, tive problemas em que declarações aparentemente corretas estavam causando erros de compilação muito estranhos que desapareceram magicamente, prefixando a typename
palavra-chave no início do declaração ... (Por exemplo, na semana passada, eu estava declarando dois iteradores como membros de outra classe de modelo e tive que fazer isso) ...
Qual é a história typename
?
Respostas:
A seguir, a citação do livro de Josuttis:
fonte
typename
(embora nem todos eles!).O post no blog de Stan Lippman sugere: -
Então, basicamente, o Stroustrup reutilizou a palavra-chave da classe sem introduzir uma nova palavra-chave que é alterada posteriormente no padrão pelos seguintes motivos
Como o exemplo dado
a gramática da linguagem interpreta mal
T::A *aObj;
como uma expressão aritmética, para que uma nova palavra-chave seja introduzida chamadatypename
instrui o compilador para tratar a instrução subseqüente como uma declaração.
É por isso que temos ambos
Você pode dar uma olhada neste post , ele definitivamente o ajudará, acabei de extrair o máximo que pude
fonte
typename
necessária, se você poderia usar a palavra-chave existenteclass
para a mesma finalidade?typename
tornou-se necessário corrigir o problema de análise, conforme descrito na resposta de Naveen, citando Josuttis. (Não acho que a inserção de umclass
neste local funcionaria.) Somente depois que a nova palavra-chave foi aceita para esse caso, ela também foi permitida nas declarações de argumento do modelo ( ou são essas definições? ), Porqueclass
sempre houve alguma enganoso.Considere o código
Infelizmente, não é necessário que o compilador seja psíquico e não sabe se T :: sometype acabará se referindo a um nome de tipo ou a um membro estático de T. Portanto, é usado
typename
para dizer:fonte
Em algumas situações em que você se refere a um membro do chamado tipo dependente (significando "dependente do parâmetro do modelo"), o compilador nem sempre pode deduzir inequivocamente o significado semântico da construção resultante, porque não sabe que tipo de nome é (ou seja, se é o nome de um tipo, o nome de um membro de dados ou o nome de outra coisa). Em casos como esse, é necessário desambiguar a situação informando explicitamente ao compilador que o nome pertence a um nome de tipo definido como um membro desse tipo dependente.
Por exemplo
Neste exemplo, a palavra-chave é
typename
necessária para a compilação do código.O mesmo acontece quando você deseja se referir a um membro do modelo do tipo dependente, ou seja, a um nome que designa um modelo. Você também precisa ajudar o compilador usando a palavra-chave
template
, embora ela seja colocada de maneira diferenteEm alguns casos, pode ser necessário usar os dois
(se obtive a sintaxe corretamente).
Obviamente, outra função da palavra
typename
- chave deve ser usada nas declarações de parâmetros do modelo.fonte
O segredo está no fato de que um modelo pode ser especializado para alguns tipos. Isso significa que também pode definir a interface completamente diferente para vários tipos. Por exemplo, você pode escrever:
Alguém pode perguntar por que isso é útil e de fato: Isso realmente parece inútil. Mas lembre-se de que, por exemplo,
std::vector<bool>
oreference
tipo parece completamente diferente do que para outrosT
s. É certo que não muda o tipo dereference
um tipo para algo diferente, mas, no entanto, pode acontecer.Agora, o que acontece se você escrever seus próprios modelos usando esse
test
modelo. Algo assimparece estar bem para você, porque você espera que esse
test<T>::ptr
seja um tipo. Mas o compilador não sabe e, de fato, ele é aconselhado pelo padrão a esperar o contrário,test<T>::ptr
não é um tipo. Para dizer ao compilador o que você espera, adicione umtypename
antes. O modelo correto se parece com issoConclusão: você deve adicionar
typename
antes sempre que usar um tipo aninhado de modelo nos seus modelos. (Obviamente, apenas se um parâmetro do modelo for usado para esse modelo interno.)fonte
Dois usos:
template
palavra-chave de argumento (em vez declass
)typename
palavra-chave informa ao compilador que um identificador é um tipo (em vez de uma variável de membro estática)fonte
Acho que todas as respostas mencionaram que a
typename
palavra - chave é usada em dois casos diferentes:a) Ao declarar um parâmetro do tipo de modelo. por exemplo
Que não há diferença entre eles e eles são exatamente os mesmos.
b) Antes de usar um nome de tipo dependente aninhado para um modelo.
Que não usar
typename
leva a erros de análise / compilação.O que quero acrescentar ao segundo caso, conforme mencionado no livro Effective C ++ , de Scot Meyers , é que há uma exceção do uso
typename
antes de um nome de tipo dependente aninhado . A exceção é que, se você usar o nome do tipo dependente aninhado como uma classe base ou em uma lista de inicialização de membros , não deverá usartypename
lá:Nota: O uso
typename
para o segundo caso (ou seja, antes do nome do tipo dependente aninhado) não é necessário desde o C ++ 20.fonte
fonte