Elaborated type specifier
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 was hidden by a non-type declaration . They may also be used to declare new class names.
Contents |
Syntax
| class-key class-name | (1) | ||||||||
enum
enum-name
|
(2) | ||||||||
class-key
attr
(optional)
identifier
;
|
(3) | ||||||||
| class-key | - | one of class , struct , union |
| class-name | - | the name of a previously-declared class type, optionally qualified , or an identifier not previously declared as a type name |
| enum-name | - | the name of a previously-declared enumeration type, optionally qualified |
| attr | - | (since C++11) any number of attributes |
Opaque enum declaration resembles form (3) , but the enum type is a complete type after an opaque enum declaration.
Explanation
Form (3) is a special case of elaborated type specifier, usually referred to as forward declaration of classes, for the description of form (3) , see Forward declaration . The following only apply to form (1) and (2) .
The class-name or enum-name in the elaborated type specifier may either be a simple identifier or be a qualified-id . The name is looked up using unqualified name lookup or qualified 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 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 }
If the name lookup does not find a previously declared type name, the elaborated-type-specifier is introduced by
class
,
struct
, or
union
(i.e. not by
enum
), and
class-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-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
If the name refers to a typedef name , a type alias , a template type parameter , or an alias template specialization , the program is ill-formed, otherwise the elaborated type specifier introduces the name into the declaration the same way a simple type specifier introduces its type-name.
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;' }
The
class-key
or
enum
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
enumkeyword must be used to refer to an enumeration type (whether scoped or unscoped) -
the
unionclass-key must be used to refer to a union -
either the
classorstructclass-key must be used to refer to a non-union class type (the keywordsclassandstructare interchangeable here).
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
When used as a
template argument
,
class
T
is a type template parameter named
T
, not an unnamed constant parameter whose type
T
is introduced by elaborated type specifier.
Keywords
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 |