[basic.lookup.qual] (original) (raw)
6 Basics [basic]
6.5 Name lookup [basic.lookup]
6.5.4 Qualified name lookup [basic.lookup.qual]
6.5.4.1 General [basic.lookup.qual.general]
The name of a class or namespace member or enumerator can be referred to after the:: scope resolution operator ([expr.prim.id.qual]) applied to anested-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 1: class A { public: static int n;};int main() { int A; A::n = 42; A b; } — _end example_]
[Note 1:
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 aqualified-id, names used before the qualified-idbeing 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 2: class X { };class C { class X { };static const int number = 50;static X arr[number];}; X C::arr[number]; — _end example_]
A name prefixed by the unary scope operator :: ([expr.prim.id.qual]) 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 ausing-directive ([namespace.qual]).
The use of ::allows a global name to be referred to even if its identifier has beenhidden.
[Example 3: struct C { typedef int I;};typedef int I1, I2;extern int* p;extern int* q; p->C::I::~I(); q->I1::~I2(); struct A { ~A();};typedef A AB;int main() { AB* p; p->AB::~AB(); } — _end example_]
6.5.4.2 Class members [class.qual]
The name shall represent one or more members of that class or of one of its base classes ([class.derived]).
[Note 2:
For example, the constructor is not an acceptable lookup result in anelaborated-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 1: struct A { A(); };struct B: public A { B(); }; A::A() { }B::B() { }B::A ba; A::A a; struct A::A a2; — _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.
6.5.4.3 Namespace members [namespace.qual]
For a namespace X and name m, the namespace-qualified lookup set is defined as follows: Let be the set of all declarations of m in X and the inline namespace set ofX ([namespace.def]) whose potential scope ([basic.scope.namespace]) would include the namespace in which m is declared at the location of the nested-name-specifier.
If is not empty, is ; otherwise, is the union of for all namespaces nominated by using-directives inX 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 is the empty set, the program is ill-formed.
Otherwise, if has exactly one member, or if the context of the reference is a using-declaration ([namespace.udecl]), is the required set of declarations of m.
Otherwise if the use ofm is not one that allows a unique declaration to be chosen from, the program is ill-formed.
[Example 1: 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(); AB::f(1); AB::f('c'); AB::x++; AB::i++; AB::h(16.8); } — _end example_]
[Note 1:
The same declaration found more than once is not an ambiguity (because it is still a unique declaration).
[Example 2: 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++; } namespace D { using A::a;} namespace BD { using namespace B;using namespace D;} void g() { BD::a++; } — _end example_]
— _end note_]
[Example 3:
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++; B::a++; A::b++; 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 introduce either 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 4: namespace A { struct x { };int x;int y;} namespace B { struct y { };} namespace C { using namespace A;using namespace B;int i = C::x; int j = C::y; } — _end example_]
[Example 5: namespace A { namespace B { void f1(int);} using namespace B;} void A::f1(int){ } — _end example_]
[Example 6: 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){ } — _end example_]