Templates
Un template est une entité C++ qui définit l'un des éléments suivants :
- une famille de classes ( class template ), qui peut être nested classes
- une famille de fonctions ( function template ), qui peut être member functions
|
(depuis C++11) |
|
(depuis C++14) |
|
(depuis C++20) |
Les modèles sont paramétrés par un ou plusieurs paramètres de modèle , de trois types : paramètres de modèle de type, paramètres de modèle constants et paramètres de modèle de modèle.
Lorsque des arguments de template sont fournis, ou, pour les templates de fonction et de classe (depuis C++17) uniquement, déduits, ils sont substitués aux paramètres du template pour obtenir une spécialisation du template, c'est-à-dire un type spécifique ou une lvalue de fonction spécifique.
Les spécialisations peuvent également être fournies explicitement : les spécialisations complètes sont autorisées pour les modèles de classe , de variable (depuis C++14) et de fonction, les spécialisations partielles sont uniquement autorisées pour les modèles de classe et les modèles de variable (depuis C++14) .
Lorsqu'une spécialisation de classe template est référencée dans un contexte qui nécessite un type d'objet complet, ou lorsqu'une spécialisation de fonction template est référencée dans un contexte qui nécessite l'existence d'une définition de fonction, le template est instancié (le code correspondant est réellement compilé), sauf si le template a déjà été explicitement spécialisé ou explicitement instancié. L'instanciation d'une classe template n'instancie aucune de ses fonctions membres sauf si elles sont également utilisées. Au moment de l'édition des liens, les instanciations identiques générées par différentes unités de traduction sont fusionnées.
La définition d'un modèle de classe doit être visible au point d'instanciation implicite, c'est pourquoi les bibliothèques de modèles fournissent généralement toutes les définitions de modèles dans les en-têtes (par exemple, la plupart des bibliothèques boost sont header-only ).
Table des matières |
Syntaxe
template <
liste-de-paramètres
>
clause-requires
(optionnel)
déclaration
|
(1) | ||||||||
export template <
liste-de-paramètres
>
déclaration
|
(2) | (jusqu'en C++11) | |||||||
template <
liste-de-paramètres
> concept
nom-concept
=
expression-contrainte
;
|
(3) | (depuis C++20) | |||||||
| 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 pack de paramètres de l'un de ceux-ci (depuis C++11) . |
| requires-clause | - | (depuis C++20) une clause requires qui spécifie les contraintes sur les arguments du template. |
| declaration | - | déclaration d'une classe (incluant struct et union) , d'une classe membre ou d'un type d'énumération membre , d'une fonction ou fonction membre , d'un membre de données statique au niveau de la portée de l'espace de noms , d'une variable ou d'un membre de données statique au niveau de la portée de la classe (depuis C++14) , ou d'un alias de template (depuis C++11) . Elle peut également définir une spécialisation de template . |
|
concept-name
constraint-expression |
- | voir contraintes et concepts |
|
export était un modificateur optionnel qui déclarait le modèle comme exporté (lorsqu'il était utilisé avec un modèle de classe, il déclarait également tous ses membres comme exportés). Les fichiers qui instanciaient des modèles 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) |
|
Cette section est incomplète
Raison : syntaxe de base, paramètres de template, et instantiations, reprendre le contenu commun entre class_template et function_template |
Identifiants de template
Un identifiant de template a l'une des syntaxes suivantes :
template-name
<
template-argument-list
(optionnel)
>
|
(1) | ||||||||
operator
op
<
template-argument-list
(optionnel)
>
|
(2) | ||||||||
operator ""
identifier
<
template-argument-list
(optionnel)
>
|
(3) |
(depuis C++11)
(obsolète) |
|||||||
operator
user-defined-string-literal
<
template-argument-list
(optionnel)
>
|
(4) | (depuis C++11) | |||||||
| template-name | - | un identifiant qui nomme un template |
| op | - | un opérateur surchargeable |
| identifier | - | un identifiant |
| user-defined-string-literal | - | "" suivi d'un identifiant |
Un identifiant de modèle simple qui désigne une spécialisation de modèle de classe désigne une classe.
Un identifiant de modèle qui nomme une spécialisation de modèle d'alias désigne un type.
Un identifiant de modèle qui nomme une spécialisation de modèle de fonction nomme une fonction.
Si toutes les conditions suivantes sont satisfaites, un identifiant de template est valide :
- Il y a au plus autant d'arguments que de paramètres ou un paramètre est un parameter pack (depuis C++11) .
- Il existe un argument pour chaque paramètre non-déductible non-pack (depuis C++11) qui n'a pas d'argument template par défaut.
- Chaque argument template correspond au paramètre template correspondant.
- La substitution de chaque argument template dans les paramètres template suivants (s'il y en a) réussit.
|
(depuis C++20) |
Un identifiant de modèle simple non valide est une erreur de compilation, sauf s'il nomme une spécialisation de fonction modèle (auquel cas SFINAE peut s'appliquer).
template<class T, T::type n = 0> class X; struct S { using type = int; }; using T1 = X<S, int, int>; // erreur : trop d'arguments using T2 = X<>; // erreur : pas d'argument par défaut pour le premier paramètre template using T3 = X<1>; // erreur : la valeur 1 ne correspond pas au paramètre de type using T4 = X<int>; // erreur : échec de substitution pour le second paramètre template using T5 = X<S>; // OK
|
Lorsque le template-name d'un simple template id désigne un modèle non-fonction contraint ou un paramètre de modèle de modèle contraint, mais pas un modèle membre qui est membre d'une spécialisation inconnue, et que tous les arguments de modèle dans le simple template id sont non-dépendants, les contraintes associées du modèle contraint doivent être satisfaites : template<typename T> concept C1 = sizeof(T) != sizeof(int); template<C1 T> struct S1 {}; template<C1 T> using Ptr = T*; S1<int>* p; // error: constraints not satisfied Ptr<int> p; // error: constraints not satisfied template<typename T> struct S2 { Ptr<int> x; }; // error, no diagnostic required template<typename T> struct S3 { Ptr<T> x; }; // OK, satisfaction is not required S3<int> x; // error: constraints not satisfied template<template<C1 T> class X> struct S4 { X<int> x; // error, no diagnostic required }; template<typename T> concept C2 = sizeof(T) == 1; template<C2 T> struct S {}; template struct S<char[2]>; // error: constraints not satisfied template<> struct S<char[2]> {}; // error: constraints not satisfied |
(depuis C++20) |
Si toutes les conditions suivantes sont satisfaites, deux identifiants de template sont same :
- Leurs template-name s ou opérateurs font référence au même modèle.
- Leurs arguments de type de modèle correspondants sont du même type.
- Les valeurs des paramètres de modèle déterminées par leurs arguments de modèle constants correspondants sont template-argument-equivalent .
- Leurs arguments de modèle de modèle correspondants font référence au même modèle.
Deux identifiants de modèle identiques font référence à la même variable, (depuis C++14) classe ou fonction.
Entité template
Une entité template (ou, dans certaines sources, « temploïde ») est toute entité définie (ou, pour une expression lambda , créée) (depuis C++11) dans une définition de template. Toutes les entités suivantes sont des entités template :
- une classe/fonction /variable (depuis C++14) template
|
(depuis C++20) |
- un membre d'une entité template (comme une fonction membre non-template d'une classe template)
- un énumérateur d'une énumération qui est une entité template
- toute entité définie ou créée dans une entité template : une classe locale, une variable locale, une fonction amie, etc
|
(depuis C++11) |
Par exemple, dans
template<typename T> struct A { void f() {} };
la fonction
A::f
n'est pas un modèle de fonction, mais est toujours considérée comme étant template.
Une
fonction template
est une fonction template ou une fonction qui est template.
Une classe template est un modèle de classe ou une classe qui est template.
|
Une variable templatée est un modèle de variable ou une variable qui est templatée. |
(depuis C++14) |
Mots-clés
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Appliqué à | Comportement publié | Comportement corrigé |
|---|---|---|---|
| CWG 2293 | C++98 |
les règles pour déterminer si un identifiant
de template est valide n'étaient pas fournies |
fournies |
| CWG 2682 |
C++98
C++14 |
les définitions de fonction template/classe template
(C++98)/variable template (C++14) manquaient |
ajoutées |
| P2308R1 | C++98 |
deux identifiants de template étaient différents si leurs
arguments de template constants correspondants n'étaient pas template-argument-équivalents |
ils sont différents si leurs valeurs de paramètres
de template constants correspondants ne sont pas template-argument-équivalentes |
Voir aussi
|
Documentation C
pour
Sélection générique
|