Elaborated type specifiers may be used to refer to a previously-declared class name (class, struct, or union) or to a previously-declared enum name even if the name washidden by a non-type declaration. They may also be used to declare new class names.
|
class-keyclass-name | (1) | |
|
enum enum-name | (2) | |
|
class-keyattr (optional)identifier; | (3) | |
|
class-key | - | one ofclass,struct,union |
class-name | - | the name of a previously-declared class type, optionallyqualified, or an identifier not previously declared as a type name |
enum-name | - | the name of a previously-declared enumeration type, optionallyqualified |
attr | - | (since C++11) any number ofattributes |
1) Elaborated type specifier for a class type.
2) Elaborated type specifier for an enumeration type.
3) A declaration that consists solely of an elaborated type specifier always declares a class type named by
identifier in the
scope that contains the declaration.
Opaque enum declaration resembles form(3), but the enum type is a complete type after an opaque enum declaration.
[edit]Explanation
Form(3) is a special case of elaborated type specifier, usually referred to asforward declaration of classes, for the description of form(3), seeForward declaration. The following only apply to form(1) and(2).
Theclass-name orenum-name in the elaborated type specifier may either be a simple identifier or be aqualified-id. The name is looked up usingunqualified name lookup orqualified name lookup, depending on their appearance. But in either case, non-type names are not considered.
class T{public:class U;private:int U;}; int main(){int T; T t;// error: the local variable T is foundclass T t;// OK: finds ::T, the local variable T is ignored T::U* u;// error: lookup of T::U finds the private data memberclass T::U* u;// OK: the data member is ignored}
If the name lookup does not find a previously declared type name, the elaborated-type-specifier is introduced byclass
,struct
, orunion
(i.e. not byenum
), andclass-name is an unqualified identifier, then the elaborated-type-specifier is a class declaration of the class-name, and the target scope is the nearest enclosing namespace or block scope.
template<typename T>struct Node{struct Node* Next;// OK: lookup of Node finds the injected-class-namestruct Data* Data;// OK: declares type Data at global scope// and also declares the data member Datafriendclass::List;// error: cannot introduce a qualified nameenum Kind* kind;// error: cannot introduce an enum}; Data* p;// OK: struct Data has been declared
If the name refers to atypedef name, atype alias, atemplate type parameter, or analias template specialization, the program is ill-formed, otherwise the elaborated type specifier introduces the name into the declaration the same way asimple type specifier introduces its type-name.
template<typename T>class Node{friendclass 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;'}
Theclass-key orenum
keyword present in the elaborated-type-specifier must agree in kind with the declaration to which the name in the elaborated-type-specifier refers.
- the
enum
keyword must be used to refer to anenumeration type (whether scoped or unscoped) - the
union
class-key must be used to refer to aunion - either the
class
orstruct
class-key must be used to refer to a non-union class type (the keywordsclass
andstruct
are interchangeable here).
enumclass E{ a, b};enum E x= E::a;// OKenumclass E y= E::b;// error: 'enum class' cannot introduce an elaborated type specifier struct A{};class A a;// OK
When used as atemplate argument,class T is a type template parameter namedT
, not an unnamed constant parameter whose typeT
is introduced by elaborated type specifier.
[edit]Keywords
class,struct,union,enum
[edit]References
- 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]
| This section is incomplete Reason: probably pull most of 9.1[class.name]/2-3 out of cpp/language/class |