typename
e class
são intercambiáveis no caso básico de especificar um modelo:
template<class T>
class Foo
{
};
e
template<typename T>
class Foo
{
};
são equivalentes.
Dito isto, há casos específicos em que há uma diferença entre typename
e class
.
O primeiro é no caso de tipos dependentes. typename
é usado para declarar quando você está referenciando um tipo aninhado que depende de outro parâmetro de modelo, como typedef
neste exemplo:
template<typename param_t>
class Foo
{
typedef typename param_t::baz sub_t;
};
O segundo que você realmente mostra na sua pergunta, embora você possa não perceber:
template < template < typename, typename > class Container, typename Type >
Ao especificar um modelo modelo , a class
palavra-chave deve ser usada como acima - é não intercambiáveis com typename
neste caso (nota: uma vez C ++ 17 palavras-chave são permitidos neste caso) .
Você também deve usar class
ao instanciar explicitamente um modelo:
template class Foo<int>;
Tenho certeza de que há outros casos que perdi, mas o ponto principal é: essas duas palavras-chave não são equivalentes e são alguns casos comuns em que você precisa usar uma ou outra.
template <typename T> typename Foo {};
, porque Foo <T> é definitivamente uma classe.std::vector<int>::value_type
não é um tipo dependente, você não precisatypename
dele - você só precisa se um tipo depende de um parâmetro do modelo, digamostemplate<class T> struct C { typedef typename std::vector<T>::value_type type; };
param_t
não é um tipo dependente. Tipos dependentes são nomes que dependem de um parâmetro do modelo , por exemplofoo<param_t>::some_type
, não os próprios parâmetros do modelo.typename
, ou sejatemplate <typename> typename C
.GCC 5
, o G ++ agora permite o nome do tipo em um parâmetro de modelo .Para nomear parâmetros do modelo
typename
eclass
são equivalentes. §14.1.2:typename
no entanto, é possível em outro contexto ao usar modelos - para sugerir ao compilador que você está se referindo a um tipo dependente. §14.6.2:Exemplo:
Sem
typename
o compilador, não se pode dizer em geral se você está se referindo a um tipo ou não.fonte
Embora não haja diferença técnica, vi os dois usados para denotar coisas ligeiramente diferentes.
Para um modelo que deve aceitar qualquer tipo como T, incluindo embutidos (como uma matriz)
Para um modelo que funcionará apenas onde T é uma classe real.
Mas lembre-se de que isso é puramente algo que algumas pessoas usam. Não é obrigatório pelo padrão ou imposto pelos compiladores
fonte
T t; int i = t.toInt();
), então você precisa de uma "classe real", e seu código não será compilado se você fornecerint
paraT
...class
implica que você não está apenas esperando um "valor", talvez apoiando alguns operadores, copie ou mova a construção e / ou atribuição, mas precise especificamente de um tipo que suporte alguma semântica de acesso de membro. Um rápido olhar para a declaração define expectativas e desencoraja, por exemplo, fornecer tiposclass
internos para parâmetros quando isso certamente seria um erro.Container
é ele próprio um modelo com dois parâmetros de tipo.fonte
template<template<class U> class V> struct C {};
Este fragmento é do livro de iniciação c ++. Embora eu tenha certeza que isso está errado.
Cada parâmetro de tipo deve ser precedido pela classe de palavra-chave ou nome do tipo:
Essas palavras-chave têm o mesmo significado e podem ser usadas alternadamente dentro de uma lista de parâmetros do modelo. Uma lista de parâmetros do modelo pode usar as duas palavras-chave:
Pode parecer mais intuitivo usar a palavra-chave typename em vez de classe para designar um parâmetro de tipo de modelo. Afinal, podemos usar tipos internos (não classe) como um argumento de tipo de modelo. Além disso, o typename indica mais claramente que o nome a seguir é um nome de tipo. No entanto, o typename foi adicionado ao C ++ depois que os modelos já estavam em uso generalizado; alguns programadores continuam a usar a classe exclusivamente
fonte