[basic.lookup.qual]

# 6 Basics [[basic]](./#basic)

## 6.5 Name lookup [[basic.lookup]](basic.lookup#qual)

### 6.5.5 Qualified name lookup [basic.lookup.qual]

#### [6.5.5.1](#general) General [[basic.lookup.qual.general]](basic.lookup.qual.general)

[1](#general-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2350)

Lookup of an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") followed by a ​::​ scope resolution operator
considers only
namespaces, types, and templates whose specializations are types[.](#general-1.sentence-1)

If a
name,[*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]"),[*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"), or[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]") is followed by a ​::​,
it shall either be
a dependent [*splice-scope-specifier*](expr.prim.id.qual#nt:splice-scope-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") ([[temp.dep.splice]](temp.dep.splice "13.8.3.5 Dependent splice specifiers")) or
it shall designate a namespace, class, enumeration, or dependent type,
and the ​::​ is never interpreted as
a complete [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#general-1.sentence-2)

[*Example [1](#general-example-1)*: class A {public:static int n;};int main() {int A;
 A::n = 42; // OK A b; // error: A does not name a type}template<int> struct B : A {};namespace N {template<int> void B(); int f() {return B<0>::n; // error: N​::​B<0> is not a type}} â *end example*]

[2](#general-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2393)

A member-qualified name is
the (unique) component name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")), if any, of

- [(2.1)](#general-2.1)

an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") or

- [(2.2)](#general-2.2)

a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") of the form[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") ​::​ or [*namespace-name*](namespace.def.general#nt:namespace-name "9.9.2.1 General [namespace.def.general]") ​::​

in the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") of a class member access expression ([[expr.ref]](expr.ref "7.6.1.5 Class member access"))[.](#general-2.sentence-1)

A [*qualified name*](#def:name,qualified "6.5.5.1 General [basic.lookup.qual.general]") is

- [(2.3)](#general-2.3)

a member-qualified name or

- [(2.4)](#general-2.4)

the terminal name of
  * [(2.4.1)](#general-2.4.1)

a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]"),

  * [(2.4.2)](#general-2.4.2)

a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]"),

  * [(2.4.3)](#general-2.4.3)

a [*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [temp.res.general]"),

  * [(2.4.4)](#general-2.4.4)

a [*qualified-namespace-specifier*](namespace.alias#nt:qualified-namespace-specifier "9.9.3 Namespace alias [namespace.alias]"), or

  * [(2.4.5)](#general-2.4.5)

a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*reflection-name*](expr.reflect#nt:reflection-name "7.6.2.10 The reflection operator [expr.reflect]"),[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"), or[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1 General [class.derived.general]") that has a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified names"))[.](#general-2.sentence-2)

The [*lookup context*](#def:lookup_context "6.5.5.1 General [basic.lookup.qual.general]") of a member-qualified name is
the type of its associated object expression
(considered dependent if the object expression is type-dependent)[.](#general-2.sentence-3)

The lookup context of any other qualified name is
the type, template, or namespace
nominated by the preceding [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")[.](#general-2.sentence-4)

[*Note [1](#general-note-1)*:

When parsing a class member access,
the name following the -> or . is
a qualified name even though it is not yet known of which kind[.](#general-2.sentence-5)

â *end note*]

[*Example [2](#general-example-2)*:

In N::C::m.Base::f()Base is a member-qualified name;
the other qualified names are C, m, and f[.](#general-2.sentence-6)

â *end example*]

[3](#general-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2440)

[*Qualified name lookup*](#def:lookup,qualified_name "6.5.5.1 General [basic.lookup.qual.general]") in a class, namespace, or enumeration performs
a search of the scope associated with it ([[class.member.lookup]](class.member.lookup "6.5.2 Member name lookup"))
except as specified below[.](#general-3.sentence-1)

Unless otherwise specified,
a qualified name undergoes qualified name lookup in its lookup context
from the point where it appears
unless the lookup context either
is dependent and is not the current instantiation ([[temp.dep.type]](temp.dep.type "13.8.3.2 Dependent types")) or
is not a class or class template[.](#general-3.sentence-2)

If nothing is found by qualified lookup for a member-qualified name
that is the terminal name ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2 Unqualified names")) of
a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and
is not dependent, it undergoes unqualified lookup[.](#general-3.sentence-3)

[*Note [2](#general-note-2)*:

During lookup for a template specialization, no names are dependent[.](#general-3.sentence-4)

â *end note*]

[*Example [3](#general-example-3)*: int f();struct A {int B, C; template<int> using D = void; using T = void; void f();};using B = A;template<int> using C = A;template<int> using D = A;template<int> using X = A;

template<class T>void g(T *p) { // as instantiated for g<A>: p->X<0>::f(); // error: A​::​X not found in ((p->X) < 0) > ​::​f() p->template X<0>::f(); // OK, ​::​X found in definition context p->B::f(); // OK, non-type A​::​B ignored p->template C<0>::f(); // error: A​::​C is not a template p->template D<0>::f(); // error: A​::​D<0> is not a class type p->T::f(); // error: A​::​T is not a class type}template void g(A*); â *end example*]

[4](#general-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2485)

If a qualified name Q follows a ~:

- [(4.1)](#general-4.1)

  If Q is a member-qualified name,
it undergoes unqualified lookup as well as qualified lookup[.](#general-4.1.sentence-1)

- [(4.2)](#general-4.2)

  Otherwise, its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") N shall nominate a type[.](#general-4.2.sentence-1)
  If N has another [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") S,Q is looked up as if its lookup context were that nominated by S[.](#general-4.2.sentence-2)

- [(4.3)](#general-4.3)

  Otherwise, if the terminal name of N is a member-qualified name M,Q is looked up as if ~Q appeared in place of M (as above)[.](#general-4.3.sentence-1)

- [(4.4)](#general-4.4)

  Otherwise, Q undergoes unqualified lookup[.](#general-4.4.sentence-1)

- [(4.5)](#general-4.5)

  Each lookup for Q considers only
types (if Q is not followed by a <) and
templates whose specializations are types[.](#general-4.5.sentence-1)
  If it finds nothing or is ambiguous, it is discarded[.](#general-4.5.sentence-2)

- [(4.6)](#general-4.6)

  The [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]") that is or contains Q shall refer to its (original) lookup context (ignoring cv-qualification) under
the interpretation established by at least one (successful) lookup performed[.](#general-4.6.sentence-1)

[*Example [4](#general-example-4)*: struct C {typedef int I;};typedef int I1, I2;extern int* p;extern int* q;void f() { p->C::I::~I(); // I is looked up in the scope of C q->I1::~I2(); // I2 is found by unqualified lookup}struct A {~A();};typedef A AB;int main() { AB* p;
 p->AB::~AB(); // explicitly calls the destructor for A} â *end example*]

#### [6.5.5.2](#class.qual) Class members [[class.qual]](class.qual)

[1](#class.qual-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2537)

In a lookup for a qualified name N whose lookup context is a class C in which function names are not ignored,[18](#footnote-18 "Lookups in which function names are ignored include names appearing in a nested-name-specifier, an elaborated-type-specifier, or a base-specifier.")

- [(1.1)](#class.qual-1.1)

if the search finds the injected-class-name of C ([[class.pre]](class.pre "11.1 Preamble")), or

- [(1.2)](#class.qual-1.2)

if N is dependent and
is the terminal name of a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"))
that names a constructor,

N is instead considered to name the constructor of class C[.](#class.qual-1.sentence-1)

Such a constructor name shall be used only
in the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") of a (friend) declaration of a constructor or
in a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")[.](#class.qual-1.sentence-2)

[*Example [1](#class.qual-example-1)*: 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 namestruct A::A a2; // object of type A â *end example*]

[18)](#footnote-18)[18)](#footnoteref-18)

Lookups in which
function names are ignored include names appearing in a[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"), an[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"), or a [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1 General [class.derived.general]")[.](#footnote-18.sentence-1)

#### [6.5.5.3](#namespace.qual) Namespace members [[namespace.qual]](namespace.qual)

[1](#namespace.qual-1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2574)

Qualified name lookup in a namespace N additionally searches
every element of the inline namespace set of N ([[namespace.def]](namespace.def "9.9.2 Namespace definition"))[.](#namespace.qual-1.sentence-1)

If nothing is found,
the results of the lookup are the results of qualified name lookup
in each namespace nominated by a [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") that precedes the point of the lookup and
inhabits N or an element of N's inline namespace set[.](#namespace.qual-1.sentence-2)

[*Note [1](#namespace.qual-note-1)*:

If a [*using-directive*](namespace.udir#nt:using-directive "9.9.4 Using namespace directive [namespace.udir]") refers to a namespace
that has already been considered, it does not affect the result[.](#namespace.qual-1.sentence-3)

â *end note*]

[*Example [1](#namespace.qual-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(); // 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*]

[2](#namespace.qual-2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2640)

[*Note [2](#namespace.qual-note-2)*:

The same declaration found more than once is not an ambiguity (because
it is still a unique declaration)[.](#namespace.qual-2.sentence-1)

[*Example [2](#namespace.qual-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++; // 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*]

[3](#namespace.qual-3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2685)

[*Example [3](#namespace.qual-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++; // 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*]

[4](#namespace.qual-4)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2713)

[*Note [3](#namespace.qual-note-3)*:

Class and enumeration declarations are not discarded
because of other declarations found in other searches[.](#namespace.qual-4.sentence-1)

â *end note*]

[*Example [4](#namespace.qual-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; // OK, A​::​x (of type int)int j = C::y; // ambiguous, A​::​y or B​::​y} â *end example*]
