The name of a class or namespace member or enumerator can be referred to after the :: scope resolution operator ([expr.prim]) applied to a nested-name-specifier that denotes its class, namespace, or enumeration. If a :: scope resolution operator in a nested-name-specifier is not preceded by a decltype-specifier, lookup of the name preceding that :: considers only namespaces, types, and templates whose specializations are types. If the name found does not designate a namespace or a class, enumeration, or dependent type, the program is ill-formed. [ Example:
class A {
public:
static int n;
};
int main() {
int A;
A::n = 42; // OK
A b; // ill-formed: A does not name a type
}— end example ]
[ Note: Multiply qualified names, such as N1::N2::N3::n, can be used to refer to members of nested classes ([class.nest]) or members of nested namespaces. — end note ]
In a declaration in which the declarator-id is a qualified-id, names used before the qualified-id being declared are looked up in the defining namespace scope; names following the qualified-id are looked up in the scope of the member's class or namespace. [ Example:
class X { };
class C {
class X { };
static const int number = 50;
static X arr[number];
};
X C::arr[number]; // ill-formed:
// equivalent to ::X C::arr[C::number];
// and not to C::X C::arr[C::number];
— end example ]
A name prefixed by the unary scope operator :: ([expr.prim]) is looked up in global scope, in the translation unit where it is used. The name shall be declared in global namespace scope or shall be a name whose declaration is visible in global scope because of a using-directive ([namespace.qual]). The use of :: allows a global name to be referred to even if its identifier has been hidden.
A name prefixed by a nested-name-specifier that nominates an enumeration type shall represent an enumerator of that enumeration.
If a pseudo-destructor-name ([expr.pseudo]) contains a nested-name-specifier, the type-names are looked up as types in the scope designated by the nested-name-specifier. Similarly, in a qualified-id of the form:
nested-name-specifieropt class-name :: ~ class-name
the second class-name is looked up in the same scope as the first. [ Example:
struct C {
typedef int I;
};
typedef int I1, I2;
extern int* p;
extern int* q;
p->C::I::~I(); // I is looked up in the scope of C
q->I1::~I2(); // I2 is looked up in the scope of the postfix-expression
struct A {
~A();
};
typedef A AB;
int main() {
AB* p;
p->AB::~AB(); // explicitly calls the destructor for A
}— end example ] [ Note: [basic.lookup.classref] describes how name lookup proceeds after the . and -> operators. — end note ]
If the nested-name-specifier of a qualified-id nominates a class, the name specified after the nested-name-specifier is looked up in the scope of the class ([class.member.lookup]), except for the cases listed below. The name shall represent one or more members of that class or of one of its base classes (Clause [class.derived]). [ Note: A class member can be referred to using a qualified-id at any point in its potential scope ([basic.scope.class]). — end note ] The exceptions to the name lookup rule above are the following:
the lookup for a destructor is as specified in [basic.lookup.qual];
a conversion-type-id of a conversion-function-id is looked up in the same manner as a conversion-type-id in a class member access (see [basic.lookup.classref]);
the names in a template-argument of a template-id are looked up in the context in which the entire postfix-expression occurs.
the lookup for a name specified in a using-declaration also finds class or enumeration names hidden within the same scope.
In a lookup in which function names are not ignored34 and the nested-name-specifier nominates a class C:
if the name specified after the nested-name-specifier, when looked up in C, is the injected-class-name of C (Clause [class]), or
in a using-declarator of a using-declaration that is a member-declaration, if the name specified after the nested-name-specifier is the same as the identifier or the simple-template-id's template-name in the last component of the nested-name-specifier,
the name is instead considered to name the constructor of class C. [ Note: For example, the constructor is not an acceptable lookup result in an elaborated-type-specifier so the constructor would not be used in place of the injected-class-name. — end note ] Such a constructor name shall be used only in the declarator-id of a declaration that names a constructor or in a using-declaration. [ Example:
struct A { A(); };
struct B: public A { B(); };
A::A() { }
B::B() { }
B::A ba; // object of type A
A::A a; // error, A::A is not a type name
struct A::A a2; // object of type A
— end example ]
A class member name hidden by a name in a nested declarative region or by the name of a derived class member can still be found if qualified by the name of its class followed by the :: operator.
Lookups in which function names are ignored include names appearing in a nested-name-specifier, an elaborated-type-specifier, or a base-specifier.
If the nested-name-specifier of a qualified-id nominates a namespace (including the case where the nested-name-specifier is ::, i.e., nominating the global namespace), the name specified after the nested-name-specifier is looked up in the scope of the namespace. The names in a template-argument of a template-id are looked up in the context in which the entire postfix-expression occurs.
For a namespace X and name m, the namespace-qualified lookup set S(X,m) is defined as follows: Let S′(X,m) be the set of all declarations of m in X and the inline namespace set of X. If S′(X,m) is not empty, S(X,m) is S′(X,m); otherwise, S(X,m) is the union of S(Ni,m) for all namespaces Ni nominated by using-directives in X and its inline namespace set.
Given X::m (where X is a user-declared namespace), or given ::m (where X is the global namespace), if S(X,m) is the empty set, the program is ill-formed. Otherwise, if S(X,m) has exactly one member, or if the context of the reference is a using-declaration, S(X,m) is the required set of declarations of m. Otherwise if the use of m is not one that allows a unique declaration to be chosen from S(X,m), the program is ill-formed. [ Example:
int x;
namespace Y {
void f(float);
void h(int);
}
namespace Z {
void h(double);
}
namespace A {
using namespace Y;
void f(int);
void g(int);
int i;
}
namespace B {
using namespace Z;
void f(char);
int i;
}
namespace AB {
using namespace A;
using namespace B;
void g();
}
void h()
{
AB::g(); // g is declared directly in AB, therefore S is { AB::g() } and AB::g() is chosen
AB::f(1); // f is not declared directly in AB so the rules are applied recursively to A and B;
// namespace Y is not searched and Y::f(float) is not considered;
// S is {A::f(int),B::f(char)} and overload resolution chooses A::f(int)
AB::f('c'); // as above but resolution chooses B::f(char)
AB::x++; // x is not declared directly in AB, and is not declared in A or B, so the rules
// are applied recursively to Y and Z, S is { } so the program is ill-formed
AB::i++; // i is not declared directly in AB so the rules are applied recursively to A and B,
// S is {A::i,B::i} so the use is ambiguous and the program is ill-formed
AB::h(16.8); // h is not declared directly in AB and not declared directly in A or B so the rules
// are applied recursively to Y and Z, S is {Y::h(int),Z::h(double)} and
// overload resolution chooses Z::h(double)
}— end example ]
[ Note: The same declaration found more than once is not an ambiguity (because it is still a unique declaration). [ Example:
namespace A {
int a;
}
namespace B {
using namespace A;
}
namespace C {
using namespace A;
}
namespace BC {
using namespace B;
using namespace C;
}
void f()
{
BC::a++; // OK: S is {A::a,A::a}
}
namespace D {
using A::a;
}
namespace BD {
using namespace B;
using namespace D;
}
void g()
{
BD::a++; // OK: S is {A::a,A::a}
}— end example ] — end note ]
[ Example: Because each referenced namespace is searched at most once, the following is well-defined:
namespace B {
int b;
}
namespace A {
using namespace B;
int a;
}
namespace B {
using namespace A;
}
void f()
{
A::a++; // OK: a declared directly in A, S is { A::a }
B::a++; // OK: both A and B searched (once), S is { A::a }
A::b++; // OK: both A and B searched (once), S is { B::b }
B::b++; // OK: b declared directly in B, S is { B::b }
}— end example ]
During the lookup of a qualified namespace member name, if the lookup finds more than one declaration of the member, and if one declaration introduces a class name or enumeration name and the other declarations either introduce the same variable, the same enumerator or a set of functions, the non-type name hides the class or enumeration name if and only if the declarations are from the same namespace; otherwise (the declarations are from different namespaces), the program is ill-formed. [ Example:
namespace A {
struct x { };
int x;
int y;
}
namespace B {
struct y { };
}
namespace C {
using namespace A;
using namespace B;
int i = C::x; // OK, A::x (of type int)
int j = C::y; // ambiguous, A::y or B::y
}— end example ]
In a declaration for a namespace member in which the declarator-id is a qualified-id, given that the qualified-id for the namespace member has the form
nested-name-specifier unqualified-id
the unqualified-id shall name a member of the namespace designated by the nested-name-specifier or of an element of the inline namespace set of that namespace. [ Example:
namespace A {
namespace B {
void f1(int);
}
using namespace B;
}
void A::f1(int){ } // ill-formed, f1 is not a member of A
— end example ] However, in such namespace member declarations, the nested-name-specifier may rely on using-directives to implicitly provide the initial part of the nested-name-specifier. [ Example:
namespace A {
namespace B {
void f1(int);
}
}
namespace C {
namespace D {
void f1(int);
}
}
using namespace A;
using namespace C::D;
void B::f1(int){ } // OK, defines A::B::f1(int)
— end example ]