cpp/language/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. They may also be used to declare new class names.

Syntax
@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 in the  that contains the declaration.

resembles form, but the enum type is a complete type after an opaque enum declaration.

Explanation
Form is a special case of elaborated type specifier, usually referred to as forward declaration of classes, for the description of form, see Forward declaration. The following only apply to form and.

The or  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.

If the name lookup does not find a previously declared type name, the elaborated-type-specifier is introduced by, , or (i.e. not by ), and  is an unqualified identifier, then the elaborated-type-specifier is a class declaration of the class-name.

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

The or  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 keyword must be used to refer to an  (whether scoped or unscoped)
 * the  must be used to refer to a
 * either the or   must be used to refer to a non-union class type (the keywords  and  are interchangeable here).

When used as a, is a type template parameter named , not an unnamed non-type parameter whose type  is introduced by elaborated type specifier.