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.
Syntax
class-keyclass-name(1) enumenum-name(2) class-keyattr(optional)identifier;(3) class-key- one of
,
,
class-name- the name of a previously-declared class type, optionally
, or an identifier not previously declared as a type name enum-name- the name of a previously-declared enumeration type, optionally
attr- (since C++11) any number of
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
that contains the 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
. 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
. The name is looked up using
or
, depending on their appearance. But in either case, non-type names are not considered.
classT{public:classU;private:intU;};intmain(){intT;Tt;// error: the local variable T is foundclassTt;// OK: finds ::T, the local variable T is ignoredT::U*u;// error: lookup of T::U finds the private data memberclassT::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<typenameT>structNode{structNode*Next;// OK: lookup of Node finds the injected-class-namestructData*Data;// OK: declares type Data at global scope// and also declares the data member Datafriendclass::List;// error: cannot introduce a qualified nameenumKind*kind;// error: cannot introduce an enum};Data*p;// OK: struct Data has been declaredIf the name refers to a
, a
, a
, or an
, the program is ill-formed, otherwise the elaborated type specifier introduces the name into the declaration the same way a
introduces its type-name.
template<typenameT>classNode{friendclassT;// error: type parameter cannot appear in an elaborated type specifier;// note that similar declaration `friend T;` is OK.};classA{};enumb{f,t};intmain(){classAa;// OK: equivalent to 'A a;'enumbflag;// 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 enum keyword must be used to refer to an
(whether scoped or unscoped)
the unionclass-key must be used to refer to a
either the class or structclass-key must be used to refer to a non-union class type (the keywords class and struct are interchangeable here).
enumclassE{a,b};enumEx=E::a;// OKenumclassEy=E::b;// error: 'enum class' cannot introduce an elaborated type specifierstructA{};classAa;// OKWhen used as a
, classT is a type template parameter named T, not an unnamed non-type 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]