Elaborated type specifier
Les spécificateurs de type élaborés peuvent être utilisés pour faire référence à un nom de classe précédemment déclaré (classe, structure ou union) ou à un nom d'énumération précédemment déclaré, même si le nom était masqué par une déclaration de non-type . Ils peuvent également être utilisés pour déclarer de nouveaux noms de classe.
Table des matières |
Syntaxe
| class-key class-name | (1) | ||||||||
enum
enum-name
|
(2) | ||||||||
class-key
attr
(optionnel)
identifier
;
|
(3) | ||||||||
| class-key | - | un parmi class , struct , union |
| class-name | - | le nom d'un type de classe précédemment déclaré, optionnellement qualifié , ou un identifiant non précédemment déclaré comme nom de type |
| enum-name | - | le nom d'un type d'énumération précédemment déclaré, optionnellement qualifié |
| attr | - | (depuis C++11) n'importe quel nombre d' attributs |
Déclaration opaque d'énumération ressemble à la forme (3) , mais le type enum est un type complet après une déclaration opaque d'énumération.
Explication
La forme (3) est un cas particulier de spécificateur de type élaboré, généralement appelé déclaration anticipée de classes. Pour la description de la forme (3) , voir Déclaration anticipée . Les éléments suivants s'appliquent uniquement aux formes (1) et (2) .
Le class-name ou enum-name dans le spécificateur de type élaboré peut être soit un identifiant simple, soit un qualified-id . Le nom est recherché en utilisant unqualified name lookup ou qualified name lookup , selon leur apparence. Mais dans les deux cas, les noms non-types ne sont pas considérés.
class T { public: class U; private: int U; }; int main() { int T; T t; // erreur : la variable locale T est trouvée class T t; // OK : trouve ::T, la variable locale T est ignorée T::U* u; // erreur : la recherche de T::U trouve le membre de données privé class T::U* u; // OK : le membre de données est ignoré }
Si la recherche de nom ne trouve pas un nom de type précédemment déclaré, le spécificateur de type élaboré est introduit par
class
,
struct
, ou
union
(c'est-à-dire pas par
enum
), et
class-name
est un identifiant non qualifié, alors le spécificateur de type élaboré est une déclaration de classe du class-name, et la portée cible est l'espace de noms englobant le plus proche ou la portée de bloc.
template<typename T> struct Node { struct Node* Next; // OK : la recherche de Node trouve le nom de classe injecté struct Data* Data; // OK : déclare le type Data dans la portée globale // et déclare également le membre de données Data friend class ::List; // erreur : ne peut pas introduire un nom qualifié enum Kind* kind; // erreur : ne peut pas introduire une énumération }; Data* p; // OK : la structure Data a été déclarée
Si le nom fait référence à un typedef name , un type alias , un template type parameter , ou une alias template specialization , le programme est mal formé, sinon le spécificateur de type élaboré introduit le nom dans la déclaration de la même manière qu'un simple type specifier introduit son type-name.
template<typename T> class Node { friend class T; // erreur : le paramètre de type ne peut pas apparaître dans un spécificateur de type élaboré ; // note : la déclaration similaire `friend T;` est correcte. }; class A {}; enum b { f, t }; int main() { class A a; // OK : équivalent à 'A a;' enum b flag; // OK : équivalent à 'b flag;' }
Le
class-key
ou le mot-clé
enum
présent dans l'elaborated-type-specifier doit correspondre en nature à la déclaration à laquelle le nom dans l'elaborated-type-specifier fait référence.
-
le mot-clé
enumdoit être utilisé pour faire référence à un type énumération (qu'il soit scopé ou non scopé) -
le
unionclass-key doit être utilisé pour faire référence à une union -
soit le
classsoit lestructclass-key doit être utilisé pour faire référence à un type classe non-union (les mots-clésclassetstructsont interchangeables ici).
enum class E { a, b }; enum E x = E::a; // OK enum class E y = E::b; // erreur : 'enum class' ne peut pas introduire un spécificateur de type élaboré struct A {}; class A a; // OK
Lorsqu'il est utilisé comme
argument de modèle
,
class
T
est un paramètre de modèle de type nommé
T
, et non un paramètre constant sans nom dont le type
T
est introduit par un spécificateur de type élaboré.
Mots-clés
Références
- Norme C++23 (ISO/IEC 14882:2024) :
-
- 6.5.6 Spécificateurs de type élaborés [basic.lookup.elab]
-
- 9.2.9.4 Spécificateurs de type élaborés [dcl.type.elab]
- Norme C++20 (ISO/CEI 14882:2020) :
-
- 6.5.4 Spécificateurs de type élaborés [basic.lookup.elab]
-
- 9.2.8.3 Spécificateurs de type élaborés [dcl.type.elab]
- Norme C++17 (ISO/IEC 14882:2017) :
-
- 6.4.4 Spécificateurs de type élaborés [basic.lookup.elab]
-
- 10.1.7.3 Spécificateurs de type élaborés [dcl.type.elab]
- Norme C++14 (ISO/CEI 14882:2014) :
-
- 3.4.4 Spécificateurs de type élaborés [basic.lookup.elab]
-
- 7.1.6.3 Spécificateurs de type élaborés [dcl.type.elab]
- Norme C++11 (ISO/IEC 14882:2011) :
-
- 3.4.4 Spécificateurs de type élaborés [basic.lookup.elab]
-
- 7.1.6.3 Spécificateurs de type élaborés [dcl.type.elab]
- Norme C++98 (ISO/CEI 14882:1998) :
-
- 3.4.4 Spécificateurs de type élaborés [basic.lookup.elab]
-
- 7.1.5.3 Spécificateurs de type élaborés [dcl.type.elab]
|
Cette section est incomplète
Raison : probablement extraire la majeure partie de 9.1[class.name]/2-3 de cpp/language/class |