Duplicate possible:
différence C++ des mots-clés ‘typename’ et ‘class’ dans les modèles
Lorsque vous définissez un modèle de fonction ou un modèle de classe en C++, vous pouvez écrire ceci:
template <class T> ...
ou on peut écrire ceci:
template <typename T> ...
Y a-t-il une bonne raison de préférer l'une à l'autre?
J'ai accepté la réponse la plus populaire (et la plus intéressante), mais la vraie réponse semble être "Non, il n'y a pas de bonne raison de préférer l'une à l'autre."
typename
.class
.Notez cependant qu'avant C++ 17, dans le cas de paramètres de modèle , l'utilisation de class
au lieu de typename
était requise. Voir réponse de l'utilisateur1428839 ci-dessous. (Mais ce cas particulier n'est pas une question de préférence, c'était une exigence de la langue.)
Stan Lippman en a parlé ici . Je pensais que c'était intéressant.
Résumé : À l'origine, Stroustrup utilisait class
pour spécifier les types dans les modèles afin d'éviter d'introduire un nouveau mot-clé. Certains membres du comité craignent que cette surcharge du mot-clé ne crée de la confusion. Plus tard, le comité a présenté un nouveau mot clé typename
pour résoudre les ambiguïtés syntaxiques et a décidé de le laisser également être utilisé pour spécifier les types de modèles afin de réduire les risques de confusion. Toutefois, pour des raisons de compatibilité ascendante, class
a gardé son sens surchargé.
Selon Scott Myers, Effective C++ (3e éd.), Élément 42 (qui doit bien entendu être la réponse ultime), la différence est "rien".
Le conseil est d'utiliser "classe" s'il est prévu que T sera toujours une classe, avec "nom_type" si d'autres types (int, char * peu importe) peuvent être attendus. Considérez cela comme un indice d'utilisation.
En complément de tous les articles ci-dessus, l'utilisation du mot clé class
est forcé (jusqu’à C++ 14 inclus) lorsqu’il s’agit de template template paramètres, par exemple:
template <template <typename, typename> class Container, typename Type>
class MyContainer: public Container<Type, std::allocator<Type>>
{ /*...*/ };
Dans cet exemple, typename Container
aurait généré une erreur de compilation, qui ressemble à ceci:
error: expected 'class' before 'Container'
Je préfère utiliser nom_type car je ne suis pas fan des mots-clés surchargés (combien de significations différentes static
a-t-il dans différents contextes?).
class
à typename
.typename
n'est pas autorisé pour les arguments de modèle. Par conséquent, pour être cohérent, vous devez utiliser class
:
template<template<class> typename MyTemplate, class Bar> class Foo { }; // :(
template<template<class> class MyTemplate, class Bar> class Foo { }; // :)
En réponse à Mike B , je préfère utiliser 'classe' car, dans un modèle, 'nomtype' a une signification surchargée, mais 'classe' n'en a pas. Prenons cet exemple de type entier vérifié:
template <class IntegerType>
class smart_integer {
public:
typedef integer_traits<Integer> traits;
IntegerType operator+=(IntegerType value){
typedef typename traits::larger_integer_t larger_t;
larger_t interm = larger_t(myValue) + larger_t(value);
if(interm > traits::max() || interm < traits::min())
throw overflow();
myValue = IntegerType(interm);
}
}
larger_integer_t
est un nom dépendant. Par conséquent, il est précédé par 'typename' pour que l'analyseur puisse reconnaître que larger_integer_t
est un type. class , d'autre part, n'a pas cette signification surchargée.
C'est ... ou je suis juste paresseux d'esprit. Je tape beaucoup plus souvent 'class' que 'typename' et le trouve beaucoup plus facile à taper. Ou cela pourrait être un signe que j'écris trop de code OO.
Juste de l'histoire pure. Citation de Stan Lippman :
La raison des deux mots-clés est historique. Dans la spécification du modèle d'origine, Stroustrup a réutilisé le mot-clé de classe existant pour spécifier un paramètre de type plutôt que d'introduire un nouveau mot-clé susceptible de détruire les programmes existants. Ce n’est pas qu’un nouveau mot-clé n’a pas été pris en compte, mais simplement qu’il n’a pas été jugé nécessaire en raison de sa perturbation potentielle. Et jusqu'à la norme ISO-C++, c'était le seul moyen de déclarer un paramètre de type.
Mais il faut utiliser typename plutôt que class ! Voir le lien pour plus d'informations, mais pensez au code suivant:
template <class T>
class Demonstration {
public:
void method() {
T::A *aObj; // oops ...
};
Cela n’a aucune importance, mais la classe donne l’impression que T ne peut être qu’une classe, alors qu’il peut bien sûr être de tout type. Donc, typename est plus précis. D'autre part, la plupart des gens utilisent la classe, ce qui est probablement plus facile à lire en général.
Autant que je sache, peu importe celui que vous utilisez. Ils sont équivalents aux yeux du compilateur. Utilisez celui que vous préférez. J'utilise normalement la classe.