Elaborierter Typ-Spezifizierer
Ausführliche Typ-Spezifizierer können verwendet werden, um auf einen zuvor deklarierten Klassennamen (class, struct oder union) oder auf einen zuvor deklarierten Enumerationsnamen zu verweisen, selbst wenn der Name durch eine Nicht-Typ-Deklaration verborgen wurde. Sie können auch verwendet werden, um neue Klassennamen zu deklarieren.
Inhalt |
[bearbeiten] Syntax
| class-key class-name | (1) | ||||||||
enum enum-name |
(2) | ||||||||
class-key attr (optional) identifier ; |
(3) | ||||||||
| class-key | - | einer von class, struct, union |
| Klassenname | - | der Name eines zuvor deklarierten Klassentyps, optional qualifiziert, oder ein Bezeichner, der nicht zuvor als Typname deklariert wurde |
| enum-name | - | der Name eines zuvor deklarierten Enumerationstyps, optional qualifiziert |
| attr | - | (seit C++11) eine beliebige Anzahl von Attributen |
Opaque Enum Deklaration ähnelt Form (3), aber der Enum-Typ ist nach einer Opaque Enum Deklaration ein vollständiger Typ.
[bearbeiten] Erklärung
Form (3) ist ein Sonderfall des ausführlichen Typ-Spezifizierers, der üblicherweise als Vorwärtsdeklaration von Klassen bezeichnet wird. Für die Beschreibung von Form (3) siehe Vorwärtsdeklaration. Das Folgende gilt nur für Form (1) und (2).
Der class-name oder enum-name im ausführlichen Typ-Spezifizierer kann entweder ein einfacher Bezeichner oder eine qualifizierte ID sein. Die Namenssuche erfolgt mithilfe von unqualifizierter Namenssuche oder qualifizierter Namenssuche, je nach Erscheinungsbild. In jedem Fall werden jedoch keine Nicht-Typ-Namen berücksichtigt.
class T { public: class U; private: int U; }; int main() { int T; T t; // error: the local variable T is found class T t; // OK: finds ::T, the local variable T is ignored T::U* u; // error: lookup of T::U finds the private data member class T::U* u; // OK: the data member is ignored }
Wenn die Namenssuche keinen zuvor deklarierten Typnamen findet, der ausführliche Typ-Spezifizierer mit class, struct oder union (d. h. nicht mit enum) eingeleitet wird und class-name ein unqualifizierter Bezeichner ist, dann ist der ausführliche Typ-Spezifizierer eine Klassendeklaration des class-name, und der Ziel-Gültigkeitsbereich ist der nächste umschließende Namespace oder Block-Gültigkeitsbereich.
template<typename T> struct Node { struct Node* Next; // OK: lookup of Node finds the injected-class-name struct Data* Data; // OK: declares type Data at global scope // and also declares the data member Data friend class ::List; // error: cannot introduce a qualified name enum Kind* kind; // error: cannot introduce an enum }; Data* p; // OK: struct Data has been declared
Wenn der Name auf einen typedef-Namen, einen Typ-Alias, einen Typ-Template-Parameter oder eine Alias-Template-Spezialisierung verweist, ist das Programm ill-formed, andernfalls führt der ausführliche Typ-Spezifizierer den Namen in die Deklaration ein, genauso wie ein einfacher Typ-Spezifizierer seinen Typ-Namen einführt.
template<typename T> class Node { friend class T; // error: type parameter cannot appear in an elaborated type specifier; // note that similar declaration `friend T;` is OK. }; class A {}; enum b { f, t }; int main() { class A a; // OK: equivalent to 'A a;' enum b flag; // OK: equivalent to 'b flag;' }
Der class-key oder das Schlüsselwort enum im ausführlichen Typ-Spezifizierer muss in seiner Art mit der Deklaration übereinstimmen, auf die sich der Name im ausführlichen Typ-Spezifizierer bezieht.
- Das Schlüsselwort
enummuss verwendet werden, um auf einen Enumerationstyp (egal ob geschachtelt oder ungeschachtelt) zu verweisen. - Der class-key
unionmuss verwendet werden, um auf eine union zu verweisen. - Entweder der class-key
classoderstructmuss verwendet werden, um auf einen Nicht-Union-Klassentyp zu verweisen (die Schlüsselwörterclassundstructsind hier austauschbar).
enum class E { a, b }; enum E x = E::a; // OK enum class E y = E::b; // error: 'enum class' cannot introduce an elaborated type specifier struct A {}; class A a; // OK
Wenn es als Template-Argument verwendet wird, ist class T ein Typ-Template-Parameter namens T und kein unbenannter Nicht-Typ-Parameter, dessen Typ T durch einen ausführlichen Typ-Spezifizierer eingeführt wird.
[bearbeiten] Schlüsselwörter
[bearbeiten] Referenzen
- C++23 Standard (ISO/IEC 14882:2024)
- 6.5.6 Elaborated type specifiers [basic.lookup.elab]
- 9.2.9.4 Elaborated type specifiers [dcl.type.elab]
- C++20 Standard (ISO/IEC 14882:2020)
- 6.5.4 Elaborated type specifiers [basic.lookup.elab]
- 9.2.8.3 Elaborated type specifiers [dcl.type.elab]
- C++17 Standard (ISO/IEC 14882:2017)
- 6.4.4 Elaborated type specifiers [basic.lookup.elab]
- 10.1.7.3 Elaborated type specifiers [dcl.type.elab]
- C++14 Standard (ISO/IEC 14882:2014)
- 3.4.4 Elaborated type specifiers [basic.lookup.elab]
- 7.1.6.3 Elaborated type specifiers [dcl.type.elab]
- C++11 Standard (ISO/IEC 14882:2011)
- 3.4.4 Elaborated type specifiers [basic.lookup.elab]
- 7.1.6.3 Elaborated type specifiers [dcl.type.elab]
- C++98 Standard (ISO/IEC 14882:1998)
- 3.4.4 Elaborated type specifiers [basic.lookup.elab]
- 7.1.5.3 Elaborated type specifiers [dcl.type.elab]
| Dieser Abschnitt ist unvollständig Grund: wahrscheinlich die meisten der 9.1[class.name]/2-3 aus cpp/language/class ziehen |