Namespaces
Variants

Class template

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Class template
Function template
Miscellaneous

Un modèle de classe définit une famille de classes.

Table des matières

Syntaxe

template < liste-de-paramètres > déclaration-de-classe (1)
template < liste-de-paramètres > requires contrainte déclaration-de-classe (2) (depuis C++20)
export template < liste-de-paramètres > déclaration-de-classe (3) (supprimé en C++11)

Explication

class-declaration - une déclaration de classe . Le nom de classe déclaré devient un nom de template.
parameter-list - une liste non-vide séparée par des virgules des paramètres de template , chacun étant soit un paramètre constant , un paramètre de type , un paramètre de template , ou un parameter pack de l'un de ceux-ci.
constraint - une expression de contrainte qui restreint les paramètres de template acceptés par ce template de classe
export était un modificateur optionnel qui déclarait le template comme exporté (lorsqu'il était utilisé avec un template de classe, il déclarait également tous ses membres comme exportés). Les fichiers qui instanciaient des templates exportés n'avaient pas besoin d'inclure leurs définitions : la déclaration était suffisante. Les implémentations de export étaient rares et en désaccord entre elles sur les détails. (jusqu'à C++11)

Instanciation de modèle de classe

Un modèle de classe en lui-même n'est pas un type, ni un objet, ni aucune autre entité. Aucun code n'est généré à partir d'un fichier source qui ne contient que des définitions de modèles. Pour que du code apparaisse, un modèle doit être instancié : les arguments du modèle doivent être fournis afin que le compilateur puisse générer une classe réelle (ou une fonction, à partir d'un modèle de fonction).

Instanciation explicite

template class-key template-name < argument-list > ; (1)
extern template class-key template-name < argument-list > ; (2) (depuis C++11)
class-key - class , struct ou union
1) Définition d'instanciation explicite
2) Déclaration d'instanciation explicite

Une définition d'instanciation explicite force l'instanciation de la classe, de la structure ou de l'union à laquelle elle se réfère. Elle peut apparaître n'importe où dans le programme après la définition du modèle, et pour une argument-list donnée, elle n'est autorisée à apparaître qu'une seule fois dans l'ensemble du programme, aucun diagnostic requis.

Une déclaration d'instanciation explicite (un extern template) ignore l'étape d'instanciation implicite : le code qui causerait autrement une instanciation implicite utilise à la place la définition d'instanciation explicite fournie ailleurs (résultant en des erreurs de liaison si aucune telle instanciation n'existe). Cela peut être utilisé pour réduire les temps de compilation en déclarant explicitement une instanciation de template dans tous les fichiers sources l'utilisant sauf un, et en la définissant explicitement dans le fichier restant.

(depuis C++11)

Classes, fonctions , variables (depuis C++14) , et les spécialisations de modèles membres peuvent être explicitement instanciées à partir de leurs modèles. Les fonctions membres, les classes membres et les membres de données statiques des modèles de classe peuvent être explicitement instanciés à partir de leurs définitions de membres.

L'instanciation explicite ne peut apparaître que dans l'espace de noms englobant du modèle, sauf si elle utilise un identifiant qualifié :

namespace N
{
    template<class T>
    class Y // définition de template
    {
        void mf() {}
    };
}
// template class Y<int>; // erreur : classe template Y non visible dans l'espace de noms global
using N::Y;
// template class Y<int>; // erreur : instanciation explicite en dehors
                          // de l'espace de noms du template
template class N::Y<char*>;       // OK : instanciation explicite
template void N::Y<double>::mf(); // OK : instanciation explicite

L'instanciation explicite n'a aucun effet si une spécialisation explicite est apparue auparavant pour le même ensemble d'arguments de template.

Seule la déclaration doit être visible lors de l'instanciation explicite d'un modèle de fonction , d'un modèle de variable (depuis C++14) , d'une fonction membre ou d'un membre de données statique d'un modèle de classe, ou d'un modèle de fonction membre. La définition complète doit apparaître avant l'instanciation explicite d'un modèle de classe, d'une classe membre d'un modèle de classe, ou d'un modèle de classe membre, à moins qu'une spécialisation explicite avec les mêmes arguments de modèle n'apparaisse avant.

Si un modèle de fonction , modèle de variable (depuis C++14) , modèle de fonction membre, ou fonction membre ou membre de données statique d'un modèle de classe est instancié explicitement avec une définition d'instanciation explicite, la définition du modèle doit être présente dans la même unité de traduction.

Lorsqu'une instanciation explicite nomme une spécialisation de modèle de classe, elle sert d'instanciation explicite du même type (déclaration ou définition) pour chacun de ses membres non hérités et non modèles qui n'a pas été précédemment explicitement spécialisé dans l'unité de traduction. Si cette instanciation explicite est une définition, elle est également une définition d'instanciation explicite uniquement pour les membres qui ont été définis à ce stade.

Les définitions d'instanciation explicite ignorent les spécificateurs d'accès des membres : les types de paramètres et les types de retour peuvent être privés.

Instanciation implicite

Lorsque le code fait référence à un template dans un contexte qui nécessite un type complètement défini, ou lorsque l'intégralité du type affecte le code, et que ce type particulier n'a pas été explicitement instancié, une instanciation implicite se produit. Par exemple, lorsqu'un objet de ce type est construit, mais pas lorsqu'un pointeur vers ce type est construit.

Cela s'applique aux membres du modèle de classe : à moins que le membre ne soit utilisé dans le programme, il n'est pas instancié et ne nécessite pas de définition.

template<class T>
struct Z // définition de template
{
    void f() {}
    void g(); // jamais définie
};
template struct Z<double>; // instanciation explicite de Z<double>
Z<int> a;                  // instanciation implicite de Z<int>
Z<char>* p;                // rien n'est instancié ici
p->f(); // instanciation implicite de Z<char> et Z<char>::f() se produit ici.
        // Z<char>::g() n'est jamais nécessaire et jamais instanciée :
        // elle n'a pas besoin d'être définie

Si un modèle de classe a été déclaré, mais non défini, au point d'instanciation, l'instanciation produit un type de classe incomplet :

template<class T>
class X;    // déclaration, pas de définition
X<char> ch; // erreur: type incomplet X<char>
Classes locales et tous les modèles utilisés dans leurs membres sont instanciés dans le cadre de l'instanciation de l'entité dans laquelle la classe ou l'énumération locale est déclarée. (depuis C++17)

Mots-clés

export (jusqu'à C++11) extern (depuis C++11)

Voir aussi