c++ - Différence de mots-clés 'typename' et 'class' dans les templates?


Pour les modèles, j'ai vu les deux déclarations:

template < typename T >
template < class T >

Quelle est la différence?

Et que signifient exactement ces mots clés dans l'exemple suivant (tiré de l'article de Wikipédia allemand sur les modèles)?

template < template < typename, typename > class Container, typename Type >
class Example
{
     Container< Type, std::allocator < Type > > baz;
};


Answers


typename et class sont interchangeables dans le cas de base de spécification d'un template:

template<class T>
class Foo
{
};

et

template<typename T>
class Foo
{
};

sont équivalents.

Cela dit, il existe des cas spécifiques où il existe une différence entre typename et class .

Le premier est dans le cas des types dépendants. typename est utilisé pour déclarer lorsque vous référencez 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;
};

Le deuxième que vous montrez réellement dans votre question, bien que vous ne puissiez pas le réaliser:

template < template < typename, typename > class Container, typename Type >

Lors de la spécification d'un modèle de template , le mot clé class DOIT être utilisé comme ci-dessus - il n'est pas interchangeable avec typename dans ce cas (note: puisque 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 manqués, mais l'essentiel 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.




Pour nommer les paramètres du template, typename et class sont équivalents. §14.1.2:

Il n'y a pas de différence sémantique entre class et typename dans un template-parameter.

typename est toutefois possible dans un autre contexte lors de l'utilisation de templates - pour indiquer au compilateur que vous faites référence à un type dépendant. §14.6.2:

Un nom utilisé dans une déclaration ou une définition de modèle et dépendant d'un paramètre de modèle est supposé ne pas nommer un type à moins que la recherche de nom applicable ne trouve un nom de type ou que le nom soit qualifié par le mot-clé typename.

Exemple:

typename some_template<T>::some_type

Sans nom de typename le compilateur ne peut pas dire en général si vous faites référence à un type ou non.




Bien qu'il n'y ait aucune différence technique, j'ai vu que les deux dénotaient des choses légèrement différentes.

Pour un modèle qui devrait accepter tout type de T, y compris les built-ins (comme un tableau)

template<typename T>
class Foo { ... }

Pour un modèle qui ne fonctionnera que là où T est une vraie classe.

template<class T>
class Foo { ... }

Mais gardez à l'esprit que c'est purement une chose de style que certaines personnes utilisent. Non mandaté par la norme ou imposé par les compilateurs




  1. Aucune différence
  2. Paramètre de type de modèle Container est lui-même un modèle avec deux paramètres de type.



Ce morceau d'extrait est du livre d'amorce de c ++. Bien que je suis sûr que c'est faux.

Chaque paramètre de type doit être précédé du mot-clé class ou typename:

// error: must precede U with either typename or class
template <typename T, U> T calc(const T&, const U&);

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:

// ok: no distinction between typename and class in a template parameter list
template <typename T, class U> calc (const T&, const U&);

Il peut sembler plus intuitif d'utiliser le mot-clé typename plutôt que class pour désigner un paramètre de type template. Après tout, nous pouvons utiliser des types intégrés (non classes) comme argument de type template. De plus, typename indique plus clairement que le nom qui suit est un nom de type. Cependant, typename a été ajouté à C ++ après que les modèles étaient déjà largement utilisés; certains programmeurs continuent à utiliser la classe exclusivement