Elaborated type specifier - cppreference.com

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

,

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

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.

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.

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

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<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

enumeration type

(whether scoped or unscoped)

the unionclass-key must be used to refer to a

union

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

template argument

, classT is a type template parameter named T, not an unnamed non-type parameter whose type T is introduced by elaborated type specifier.

Keywords

class

,

struct

,

union

,

enum

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]