template - typename c++




Utilisez 'class' ou 'typename' pour les paramètres du template? (7)

Dupliquer possible:
Différence C ++ des mots-clés 'typename' et 'class' dans les templates

Lors de la définition d'un modèle de fonction ou d'un modèle de classe en C ++, on peut é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'un à l'autre?

J'ai accepté la réponse la plus populaire (et intéressante), mais la vraie réponse semble être "Non, il n'y a pas de bonne raison de préférer l'un à l'autre".

  • Ils sont équivalents (sauf comme indiqué ci-dessous).
  • Certaines personnes ont des raisons de toujours utiliser typename .
  • Certaines personnes ont des raisons de toujours utiliser la class .
  • Certaines personnes ont des raisons d'utiliser les deux.
  • Certaines personnes ne se soucient pas de celui qu'ils utilisent.

Notez toutefois que dans le cas de paramètres de modèle de modèle , l'utilisation de class place de typename est requise. Voir la réponse de user1428839 ci-dessous. (Mais ce cas particulier n'est pas une question de préférence, c'est une exigence de la langue.) (Aussi cela va changer avec c++17 )


Il y a une différence, et vous devriez préférer la class au typename .

Mais pourquoi?

typename est illégal pour les arguments du modèle de template, donc 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 { };    //  :)

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.


En plus de tous les messages ci-dessus, l'utilisation du mot - clé class est forcée ( edit: jusqu'à et y compris C ++ 14 ) lorsqu'il s'agit de paramètres de modèle de template , par exemple:

template <template <typename, typename> class Container, typename Type>
class MyContainer: public Container<Type, std::allocator<Type>>
{ /*...*/ };

Dans cet exemple, le nom de typename Container aurait généré une erreur de compilation, quelque chose comme ceci:

error: expected 'class' before 'Container'

voir http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4051.html pour l'acceptation du nom de type dans le modèle de modèle sur C ++ 14.


En réponse à Mike B , je préfère utiliser 'class' car, dans un template, 'typename' a une signification surchargée, mais 'class' ne l'est pas. Prenez 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, donc il nécessite 'typename' pour le précéder afin que l'analyseur puisse reconnaître que larger_integer_t est un type. classe , d'autre part, n'a pas une telle signification surchargée.

Ça ... ou je suis juste paresseux de cœur. Je tape beaucoup plus souvent 'class' que 'typename', et trouve donc beaucoup plus facile à taper. Ou cela pourrait être un signe que j'écris trop de code OO.


Je préfère utiliser le nom de fichier parce que je ne suis pas un fan de mots-clés surchargés (jeez - combien de significations différentes a le static pour différents contextes différents?).


Juste l'histoire pure. Citation de Stan Lippman :

La raison de ces deux mots clés est historique. Dans la spécification de modèle d'origine, Stroustrup réutilisait le mot-clé de classe existant pour spécifier un paramètre de type plutôt que d'introduire un nouveau mot-clé qui pouvait bien sûr interrompre 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 compte tenu 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 le typename plutôt que la classe ! Consultez le lien pour plus d'informations, mais pensez au code suivant:

template <class T>
class Demonstration { 
public:
void method() {
   T::A *aObj; // oops ...
};

Stan Lippman en a parlé here . Je pensais que c'était intéressant.

Résumé : À l'origine, Stroustrup utilisait la class pour spécifier les types dans les modèles afin d'éviter d'introduire un nouveau mot-clé. Certains membres du comité craignaient que cette surcharge du mot-clé n'entraîne de la confusion. Plus tard, le comité a introduit un nouveau nom de mot- typename pour résoudre l'ambiguïté syntaxique, et a décidé de le laisser également utiliser pour spécifier les types de modèles afin de réduire la confusion, mais pour la rétrocompatibilité, la class gardait sa signification surchargée.





templates