Última atualização:2026-10-12
Análise do código-fonte do STL typename¶
O código-fonte de baixo nível da STL contém as linhas abaixo, com typedef usado em conjunto com typename; parecem bem complexas — o que afinal significam? Vamos analisar isso juntos hoje!
template<typename _Iterator>
struct iterator_traits
{
typedef typename _Iterator::iterator_category iterator_category;
typedef typename _Iterator::value_type value_type;
typedef typename _Iterator::difference_type difference_type;
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
Usos comuns de typename¶
Primeiro, vamos aprender os usos comuns de typename:
O acima é apenas um programa de exemplo; para escrever uma comparação completa de tamanho, seria preciso considerar versões especializadas. Talvez você perceba que trocar o typename do código acima por class também funciona — muito bem! Surge então a dúvida: há diferença entre as duas formas? Consultando o C++ Primer, descobrimos que são exatamente iguais.
Escopo de classe¶
Ao acessar nomes de dentro de uma classe fora dela, pode-se usar o operador de escopo de classe. Chamadas da forma MyClass::name normalmente se enquadram em três casos: dados-membro estáticos, funções-membro estáticas e tipos aninhados:
struct MyClass {
static int A; //静态成员
static int B(){cout<<"B()"<<endl; return 100;} //静态函数
typedef int C; //嵌套类型
struct A1 { //嵌套类型
static int s;
};
};
Na chamada, pode-se chamar diretamente:
Tentando um exemplo completo¶
Voltemos a um exemplo com typename:
Qual é o propósito deste código? A primeira reação da maioria das pessoas pode ser: o autor quer definir um ponteiro iter, cujo tipo apontado é o iterator contido no escopo da classe T. Pode existir uma estrutura assim, contendo o tipo iterator:
A chamada é a seguinte:
Dessa forma, a linha de código com iter fica evidente: é um ponteiro para o tipo MyIterator::iterator. Supomos que seja isso — mas será que é?
Porém, e se for algo como T::iterator? T é um parâmetro de tipo no template; só se saberá de qual tipo se trata quando o template for instanciado, sem falar no iterator interno. Pela introdução anterior ao escopo de classe, sabemos que T::iterator pode, na verdade, ser qualquer um destes três tipos:
- dado-membro estático
- função-membro estática
- tipo aninhado
O ContainsAType::iterator do exemplo anterior é um tipo aninhado, sem problema algum. Mas e se for um dado-membro estático? Se o tipo usado para instanciar a função de template foo for assim:
Então T::iterator * iter; é instanciado pelo compilador como MyIterator::iterator * iter; — o que é isso? À frente há uma variável-membro estática, e não um tipo; isso se torna uma expressão de multiplicação, só que iter não está definido aqui, e o compilador reportará um erro:
typename¶
Para nomes usados em definições de templates que dependem de parâmetros de template, o compilador só tratará o nome como um tipo se o tipo existir nos parâmetros da instanciação, ou se o nome for precedido da palavra-chave typename. Fora esses dois casos, jamais será tratado como tipo.
Portanto, se você quiser dizer diretamente ao compilador que T::iterator é um tipo, e não uma variável, basta qualificá-lo com typename:
Assim, o compilador consegue determinar que T::iterator é um tipo, sem precisar esperar até a instanciação, eliminando a ambiguidade mencionada antes.
Analisando o código-fonte¶
De volta ao código-fonte da STL
template<typename _Iterator>
struct iterator_traits
{
typedef typename _Iterator::iterator_category iterator_category;
typedef typename _Iterator::value_type value_type;
typedef typename _Iterator::difference_type difference_type;
typedef typename _Iterator::pointer pointer;
typedef typename _Iterator::reference reference;
};
Vendo o acima, fica tudo claro de imediato: nada mais é do que usar typename para dizer ao compilador que _Iterator::iterator_category é um tipo e então renomeá-lo com typedef; os demais são análogos!
Tópicos relacionados¶
- Análise do código-fonte do STL array | C++那些事
- Análise aprofundada do STL string | C++那些事
- Questões de entrevista sobre STL string explicadas | C++那些事
- Análise do código-fonte do STL deque | C++那些事
- STL otimização de classe base vazia EBO | C++那些事
- STL implementação manual de tabela hash | C++那些事
- STL hashtable tabela hash | C++那些事
- Análise do código-fonte dos iteradores da STL | C++那些事
- Análise do código-fonte do STL list | C++那些事
- STL map e multimap | C++那些事