The point of declaration for a name is immediately after its complete declarator (Clause [dcl.decl]) and before its initializer (if any), except as noted below. [ Example:
int x = 12;{ int x = x; }
Here the second x is initialized with its own (indeterminate) value. — end example ]
[ Note: a name from an outer scope remains visible up to the point of declaration of the name that hides it.[ Example:
const int i = 2;{ int i[i]; }
declares a block-scope array of two integers. — end example ] — end note ]
The point of declaration for a class or class template first declared by a class-specifier is immediately after the identifier or simple-template-id (if any) in its class-head (Clause [class]). The point of declaration for an enumeration is immediately after the identifier (if any) in either its enum-specifier ([dcl.enum]) or its first opaque-enum-declaration ([dcl.enum]), whichever comes first. The point of declaration of an alias or alias template immediately follows the type-id to which the alias refers.
The point of declaration for an enumerator is immediately after its enumerator-definition.[ Example:
const int x = 12;{ enum { x = x }; }
Here, the enumerator x is initialized with the value of the constant x, namely 12. — end example ]
After the point of declaration of a class member, the member name can be looked up in the scope of its class. [ Note: this is true even if the class is an incomplete class. For example,
struct X {
enum E { z = 16 };
int b[X::z]; // OK
};
— end note ]
The point of declaration of a class first declared in an elaborated-type-specifier is as follows:
for a declaration of the form
class-key attribute-specifier-seqopt identifier ;
the identifier is declared to be a class-name in the scope that contains the declaration, otherwise
for an elaborated-type-specifier of the form
class-key identifier
if the elaborated-type-specifier is used in the decl-specifier-seq or parameter-declaration-clause of a function defined in namespace scope, the identifier is declared as a class-name in the namespace that contains the declaration; otherwise, except as a friend declaration, the identifier is declared in the smallest namespace or block scope that contains the declaration. [ Note: These rules also apply within templates. — end note ] [ Note: Other forms of elaborated-type-specifier do not declare a new name, and therefore must refer to an existing type-name. See [basic.lookup.elab] and [dcl.type.elab]. — end note ]
The point of declaration for an injected-class-name (Clause [class]) is immediately following the opening brace of the class definition.
The point of declaration for a function-local predefined variable ([dcl.fct.def]) is immediately before the function-body of a function definition.
The point of declaration for a template parameter is immediately after its complete template-parameter. [ Example:
typedef unsigned char T; template<class T = T // lookup finds the typedef name of unsigned char , T // lookup finds the template parameter N = 0> struct A { };
— end example ]
[ Note: Friend declarations refer to functions or classes that are members of the nearest enclosing namespace, but they do not introduce new names into that namespace ([namespace.memdef]). Function declarations at block scope and variable declarations with the extern specifier at block scope refer to declarations that are members of an enclosing namespace, but they do not introduce new names into that scope. — end note ]
[ Note: For point of instantiation of a template, see [temp.point]. — end note ]