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

Los especificadores de tipo elaborados pueden utilizarse para referirse a un nombre de clase previamente declarado (class, struct o union) o a un nombre de enumeración previamente declarado incluso si el nombre estaba oculto por una declaración de no-tipo . También pueden utilizarse para declarar nuevos nombres de clase.

Contenidos

Sintaxis

class-key class-name (1)
enum enum-name (2)
class-key attr  (opcional) identifier ; (3)
class-key - uno de class , struct , union
class-name - el nombre de un tipo de clase declarado previamente, opcionalmente calificado , o un identificador no declarado previamente como nombre de tipo
enum-name - el nombre de un tipo de enumeración declarado previamente, opcionalmente calificado
attr - (desde C++11) cualquier número de atributos
1) Especificador de tipo elaborado para un tipo de clase.
2) Especificador de tipo elaborado para un tipo de enumeración.
3) Una declaración que consiste únicamente en un especificador de tipo elaborado siempre declara un tipo de clase denominado por el identifier en el scope que contiene la declaración.

Declaración de enumeración opaca se asemeja a la forma (3) , pero el tipo de enumeración es un tipo completo después de una declaración de enumeración opaca.

Explicación

La forma (3) es un caso especial de especificador de tipo elaborado, comúnmente referido como declaración anticipada de clases, para la descripción de la forma (3) , ver Forward declaration . Lo siguiente aplica únicamente a las formas (1) y (2) .

El class-name o enum-name en el especificador de tipo elaborado puede ser un identificador simple o un qualified-id . El nombre se busca utilizando unqualified name lookup o qualified name lookup , dependiendo de su apariencia. Pero en cualquier caso, los nombres que no son de tipo no se consideran.

class T
{
public:
    class U;
private:
    int U;
};
int main()
{
    int T; // error: se encuentra la variable local T
    class T t; // OK: encuentra ::T, se ignora la variable local T
    T::U* u; // error: la búsqueda de T::U encuentra el miembro de datos privado
    class T::U* u; // OK: se ignora el miembro de datos
}

Si la búsqueda de nombre no encuentra un nombre de tipo previamente declarado, el especificador de tipo elaborado es introducido por class , struct , o union (es decir, no por enum ), y class-name es un identificador no calificado, entonces el especificador de tipo elaborado es una declaración de clase del class-name, y el ámbito destino es el espacio de nombres o ámbito de bloque más cercano que lo contiene.

template<typename T>
struct Node
{
    struct Node* Next; // OK: la búsqueda de Node encuentra el nombre de clase inyectado
    struct Data* Data; // OK: declara el tipo Data en el ámbito global
                       // y también declara el miembro de datos Data
    friend class ::List; // error: no se puede introducir un nombre calificado
    enum Kind* kind; // error: no se puede introducir una enumeración
};
Data* p; // OK: la estructura Data ha sido declarada

Si el nombre se refiere a un typedef name , un type alias , un template type parameter , o una alias template specialization , el programa está mal formado; de lo contrario, el especificador de tipo elaborado introduce el nombre en la declaración de la misma manera que un simple type specifier introduce su type-name.

template<typename T>
class Node
{
    friend class T; // error: el parámetro de tipo no puede aparecer en un especificador de tipo elaborado;
                    // nota: la declaración similar `friend T;` es válida.
};
class A {};
enum b { f, t };
int main()
{
    class A a; // OK: equivalente a 'A a;'
    enum b flag; // OK: equivalente a 'b flag;'
}

La class-key o la palabra clave enum presente en el elaborated-type-specifier debe coincidir en tipo con la declaración a la que se refiere el nombre en el elaborated-type-specifier.

  • la palabra clave enum debe usarse para referirse a un tipo de enumeración (ya sea con ámbito o sin ámbito)
  • la palabra clave union class-key debe usarse para referirse a una union
  • cualquiera de las palabras clave class o struct class-key debe usarse para referirse a un tipo de clase no unión (las palabras clave class y struct son intercambiables aquí).
enum class E { a, b };
enum E x = E::a; // CORRECTO
enum class E y = E::b; // error: 'enum class' no puede introducir un especificador de tipo elaborado
struct A {};
class A a; // CORRECTO

Cuando se utiliza como un argumento de plantilla , class T es un parámetro de plantilla de tipo llamado T , no un parámetro constante sin nombre cuyo tipo T es introducido por un especificador de tipo elaborado.

Palabras clave

class , struct , union , enum

Referencias

  • Estándar C++23 (ISO/IEC 14882:2024):
  • 6.5.6 Especificadores de tipo elaborados [basic.lookup.elab]
  • 9.2.9.4 Especificadores de tipo elaborados [dcl.type.elab]
  • Estándar C++20 (ISO/IEC 14882:2020):
  • 6.5.4 Especificadores de tipo elaborados [basic.lookup.elab]
  • 9.2.8.3 Especificadores de tipo elaborados [dcl.type.elab]
  • Estándar C++17 (ISO/IEC 14882:2017):
  • 6.4.4 Especificadores de tipo elaborados [basic.lookup.elab]
  • 10.1.7.3 Especificadores de tipo elaborados [dcl.type.elab]
  • Estándar C++14 (ISO/IEC 14882:2014):
  • 3.4.4 Especificadores de tipo elaborados [basic.lookup.elab]
  • 7.1.6.3 Especificadores de tipo elaborados [dcl.type.elab]
  • Estándar C++11 (ISO/IEC 14882:2011):
  • 3.4.4 Especificadores de tipo elaborados [basic.lookup.elab]
  • 7.1.6.3 Especificadores de tipo elaborados [dcl.type.elab]
  • Estándar C++98 (ISO/IEC 14882:1998):
  • 3.4.4 Especificadores de tipo elaborados [basic.lookup.elab]
  • 7.1.5.3 Especificadores de tipo elaborados [dcl.type.elab]