typename
et class
sont interchangeables dans le cas de base de la spécification d'un modèle:
template<class T>
class Foo
{
};
et
template<typename T>
class Foo
{
};
sont équivalents.
Cela dit, il existe des cas spécifiques où il y a une différence entre typename
etclass
.
Le premier concerne les types dépendants. typename
est utilisé pour déclarer lorsque vous faites référence à un type imbriqué qui dépend d'un autre paramètre de modèle, tel que typedef
dans cet exemple:
template<typename param_t>
class Foo
{
typedef typename param_t::baz sub_t;
};
La deuxième que vous montrez réellement dans votre question, même si vous ne vous en rendez peut-être pas compte:
template < template < typename, typename > class Container, typename Type >
Lors de la spécification d'un modèle de modèle , le class
mot clé DOIT être utilisé comme ci-dessus - il n'est pas interchangeable avec typename
dans ce cas (remarque: depuis C ++ 17, les deux mots clés sont autorisés dans ce cas) .
Vous devez également utiliser class
lors de l'instanciation explicite d'un modèle:
template class Foo<int>;
Je suis sûr qu'il y a d'autres cas que j'ai ratés, mais le résultat est: ces deux mots clés ne sont pas équivalents, et ce sont des cas courants où vous devez utiliser l'un ou l'autre.
template <typename T> typename Foo {};
, car Foo <T> est certainement une classe.std::vector<int>::value_type
n'est pas un type dépendant, vous n'en avez pas besointypename
- vous n'en avez besoin que si un type dépend d'un paramètre de modèle, par exempletemplate<class T> struct C { typedef typename std::vector<T>::value_type type; };
param_t
n'est pas un type dépendant. Les types dépendants sont des noms qui dépendent d'un paramètre de modèle , par exemplefoo<param_t>::some_type
, pas des paramètres de modèle eux-mêmes.typename
, c'est à diretemplate <typename> typename C
.GCC 5
, G ++ autorise désormais le nom de type dans un paramètre de modèle de modèle .Pour nommer les paramètres du modèle,
typename
etclass
sont équivalents. §14.1.2:typename
cependant, il est possible dans un autre contexte lorsque vous utilisez des modèles - d'indiquer au compilateur que vous faites référence à un type dépendant. §14.6.2:Exemple:
Sans
typename
le compilateur, vous ne pouvez pas dire en général si vous faites référence à un type ou non.la source
Bien qu'il n'y ait pas de différence technique, j'ai vu que les deux désignaient des choses légèrement différentes.
Pour un modèle qui devrait accepter tout type comme T, y compris les éléments intégrés (tels qu'un tableau)
Pour un modèle qui ne fonctionnera que lorsque T est une vraie classe.
Mais gardez à l'esprit que certaines personnes utilisent uniquement le style. Non mandaté par la norme ou imposé par les compilateurs
la source
T t; int i = t.toInt();
), alors vous avez besoin d'une "vraie classe", et votre code ne se compilera pas si vous fournissezint
pourT
...class
implique que vous n'attendez pas seulement une "valeur" prenant peut-être en charge certains opérateurs, copiez ou déplacez la construction et / ou l'affectation, mais avez spécifiquement besoin d'un type prenant en charge certaines sémantiques d'accès aux membres. Le coup d'œil le plus rapide sur la déclaration définit ensuite les attentes et décourage, par exemple, la fourniture de types intégrés pour lesclass
paramètres alors que ce serait certainement une erreur.Container
est lui-même un modèle avec deux paramètres de type.la source
template<template<class U> class V> struct C {};
Cet extrait est extrait du livre de base c ++. Même si je suis sûr que c'est faux.
Chaque paramètre de type doit être précédé de la classe de mots-clés ou du nom de type:
Ces mots clés ont la même signification et peuvent être utilisés de manière interchangeable dans une liste de paramètres de modèle. Une liste de paramètres de modèle peut utiliser les deux mots clés:
Il peut sembler plus intuitif d'utiliser le mot-clé typename plutôt que class pour désigner un paramètre de type de modèle. Après tout, nous pouvons utiliser des types intégrés (non-classe) comme argument de type de modèle. De plus, le nom de type indique plus clairement que le nom qui suit est un nom de type. Cependant, le nom de type a été ajouté à C ++ après que les modèles étaient déjà largement utilisés; certains programmeurs continuent d'utiliser exclusivement la classe
la source