Elaborated type specifier
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 |
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
enumdebe usarse para referirse a un tipo de enumeración (ya sea con ámbito o sin ámbito) -
la palabra clave
unionclass-key debe usarse para referirse a una union -
cualquiera de las palabras clave
classostructclass-key debe usarse para referirse a un tipo de clase no unión (las palabras claveclassystructson 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
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]
|
Esta sección está incompleta
Razón: probablemente extraer la mayor parte de 9.1[class.name]/2-3 de cpp/language/class |