[basic.lookup.qual] (original) (raw)

6 Basics [basic]

6.5 Name lookup [basic.lookup]

6.5.3 Qualified name lookup [basic.lookup.qual]

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

:

class A { public: static int n; }; int main() { int A; A::n = 42;
A b;
}

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

:

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

:

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

:

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

:

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.3.2 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, 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

:

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

:

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++;
}

namespace D { using A::a; }

namespace BD { using namespace B; using namespace D; }

void g() { BD::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++;
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

:

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

:

namespace A { namespace B { void f1(int); } using namespace B; } void A::f1(int){ }

end example

]

[ 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){ }

end example

]