An elaborated-type-specifier ([dcl.type.elab]) may be used to refer to a previously declared class-name or enum-name even though the name has been hidden by a non-type declaration ([basic.scope.hiding]).
If the elaborated-type-specifier has no nested-name-specifier, and unless the elaborated-type-specifier appears in a declaration with the following form:
class-key attribute-specifier-seqopt identifier ;
the identifier is looked up according to [basic.lookup.unqual] but ignoring any non-type names that have been declared. If the elaborated-type-specifier is introduced by the enum keyword and this lookup does not find a previously declared type-name, the elaborated-type-specifier is ill-formed. If the elaborated-type-specifier is introduced by the class-key and this lookup does not find a previously declared type-name, or if the elaborated-type-specifier appears in a declaration with the form:
class-key attribute-specifier-seqopt identifier ;
the elaborated-type-specifier is a declaration that introduces the class-name as described in [basic.scope.pdecl].
If the elaborated-type-specifier has a nested-name-specifier, qualified name lookup is performed, as described in [basic.lookup.qual], but ignoring any non-type names that have been declared. If the name lookup does not find a previously declared type-name, the elaborated-type-specifier is ill-formed. [ Example:
struct Node { struct Node* Next; // OK: Refers to Node at global scope struct Data* Data; // OK: Declares type Data // at global scope and member Data }; struct Data { struct Node* Node; // OK: Refers to Node at global scope friend struct ::Glob; // error: Glob is not declared // cannot introduce a qualified type ([dcl.type.elab]) friend struct Glob; // OK: Refers to (as yet) undeclared Glob // at global scope. /* ... */ }; struct Base { struct Data; // OK: Declares nested Data struct ::Data* thatData; // OK: Refers to ::Data struct Base::Data* thisData; // OK: Refers to nested Data friend class ::Data; // OK: global Data is a friend friend class Data; // OK: nested Data is a friend struct Data { /* ... */ }; // Defines nested Data }; struct Data; // OK: Redeclares Data at global scope struct ::Data; // error: cannot introduce a qualified type ([dcl.type.elab]) struct Base::Data; // error: cannot introduce a qualified type ([dcl.type.elab]) struct Base::Datum; // error: Datum undefined struct Base::Data* pBase; // OK: refers to nested Data