Namespaces
Variants

Elaborated type specifier

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
Miscellaneous

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
1) Spécificateur de type élaboré pour un type classe.
2) Spécificateur de type élaboré pour un type énumération.
3) Une déclaration qui consiste uniquement en un spécificateur de type élaboré déclare toujours un type de classe nommé par identifier dans la portée qui contient la déclaration.

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é enum doit être utilisé pour faire référence à un type énumération (qu'il soit scopé ou non scopé)
  • le union class-key doit être utilisé pour faire référence à une union
  • soit le class soit le struct class-key doit être utilisé pour faire référence à un type classe non-union (les mots-clés class et struct sont 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

class , struct , union , enum

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]