Qualified name lookup - cppreference.com

##### cppreference.com

##### Search

Create account

##### Namespaces

- Page
- Discussion

##### Variants

##### Views

- View
- Edit
- History

##### Actions

# Qualified name lookup

From cppreference.com
< cpp‎ | language

A qualified name is a name that appears on the right hand side of the scope resolution operator `::` (see also qualified identifiers). A qualified name may refer to a

- class member (including static and non-static functions, types, templates, etc)
- namespace member (including another namespace)
- enumerator

If there is nothing on the left hand side of the `::`, the lookup considers only declarations made in the global namespace scope (or introduced into the global namespace by a using declaration). This makes it possible to refer to such names even if they were hidden by a local declaration:

    #include <iostream>
    int main()
    {
      struct std{};
      std::cout << "fail\n"; // Error: unqualified lookup for 'std' finds the struct
      ::std::cout << "ok\n"; // OK: ::std finds the namespace std
    }

Before name lookup can be performed for the name on the right hand side of `::`, lookup must be completed for the name on its left hand side (unless a decltype expression is used, or there is nothing on the left). This lookup, which may be qualified or unqualified, depending on whether there's another `::` to the left of that name, considers only namespaces, class types, enumerations, and templates whose specializations are types:

    struct A {
      static int n;
    };
    int main() {
      int A;
      A::n = 42;    // OK: unqualified lookup of A to the left of :: ignores the variable
      A b;          // error: unqualified lookup of A finds the variable A
    }

When a qualified name is used as a declarator, then lookup of all names used in the same declarator that follow that qualified name, but not the names that precede it, is performed as if qualified the same way:

    class X { };
    constexpr int number = 100;
    class C {
      class X { };
      static const int number = 50;
      static X arr[number];
    };
    X C::arr[number], brr[number];   // Error
      // Every name in the declarator "C::arr[number]" after "C::arr"
      // is looked up within C::, but the names before C::arr are unaffected,
      // The names in the second declarator ("brr[number]") are also unaffected
      // equivalent to:
      // "::X C::arr[C::number], brr[::number]"
    C::X C::arr[number], brr[number]; // Compiles, size of arr is 50, size of brr is 100

If the name on the right hand side of `::` is a destructor or pseudo-destructor (that is, the character `~` followed by an identifier), that identifier is looked up in the same scope as the name on the left hand side of `::`

    struct C { typedef int I; };
    typedef int I1, I2;
    extern int *p, *q;
    struct A { ~A(); };
    typedef A AB;
    int main() {
      p->C::I::~I(); // the name I after ~ is looked up in the same scope as I before ::
                     // (that is, within the scope of C, so it finds C::I)
      q->I1::~I2();  // The name I2 is looked up in the same scope as I1
                     // that is, from the current scope, so it finds ::I2
      AB x;
      x.AB::~AB(); // The name AB after ~ is looked up in the same scope as AB before ::
                   // that is, from the current scope, so it finds ::AB
    }

#### Enumerators If the lookup of the left-hand side name comes up with an enumeration (either scoped or unscoped), the lookup of the right-hand side must result in an enumerator that belongs that enumeration, otherwise the program is ill-formed. | (since C++11)

#### [edit] Class members

If the lookup of the left hand side name comes up with a class/struct or union name, the name on the right hand side of `::` is looked up in the scope of that class (and so may find a declaration of a member of that class or of its base), with the following exceptions

- destructor name is looked up as described above (in the scope of the name to the left of ::)
- user-defined conversion function name is (TODO)
- names used in template arguments are looked up in the current scope (not in the scope of the template name)
- names in using-declarations also consider class/enum names that are hidden in current scope

| This section is incomplete Reason: micro-examples for the above

If the right hand side of `::` names the same class as the left hand side, the name designates the constructor of that class. Such qualified name can only be used in a declaration of a constructor and in the using-declaration for an inheriting constructor. In those lookups where function names are ignored (that is, when looking up a name on the left of `::`, when looking up a name in elaborated type specifier, or base specifier), the same syntax resolves to the injected-class-name:

    struct A { A(); };
    struct B : A { B(); };
    A::A() { } // A::A names a constructor, used in a declaration
    B::B() { } // B::B names a constructor, used in a declaration
    B::A ba;   // B::A names the type A (looked up in the scope of B)
    A::A a;    // Error, A::A does not name a type

    struct A::A a2; // OK: lookup in elaborated type specifier ignores functions
                    // so A::A simply names the class A as seen from within the scope of A
                    // (that is, the injected-class-name)

Qualified name lookup can be used to access a class member that is hidden by a nested declaration or by a derived class. A call to a qualified member function is never virtual

    struct B { virtual void foo(); };
    struct D : B { void foo() override; };
    int main()
    {
        D x;
        B& b = x;
        b.foo(); // calls D::foo (virtual dispatch)
        b.B::foo(); // calls B::foo (static dispatch)
    }

#### [edit] Namespace members

If the name on the left of `::` refers to a namespace or if there is nothing on the left of `::` (in which case it refers to the global namespace), the name that appears on the right hand side of `::` is looked up in the scope of that namespace, except that

- names used in template arguments are looked up in the current scope

    namespace N {
       template<typename T> struct foo {};
       struct X {};
    }
    N::foo<X> x; // error: X is looked up as ::X, not as N::X

Qualified lookup within the scope of a namespace `N` first considers all declarations that are located in `N` and all declarations that are located in the inline namespace members of `N` (and, transitively, in their inline namespace members). If there are no declarations in that set then it considers declarations in all namespaces named by using-directives found in `N` and in all transitive inline namespace members of `N`. The rules are applied recursively:

    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 is searched, AB::g found by lookup and is chosen AB::g(void)
                // (A and B are not searched)
      AB::f(1); // First, AB is searched, there is no f
                // Then, A, B are searched
                // A::f, B::f found by lookup (but Y is not searched so Y::f is not considered)
                // overload resolution picks A::f(int)
      AB::x++;    // First, AB is searched, there is no x
                  // Then A, B are searched. There is no x
                  // Then Y and Z are searched. There is still no x: this is an error
      AB::i++;  // AB is searched, there is no i
                // Then A, B are searched. A::i and B::i found by lookup: this is an error
      AB::h(16.8);  // First, AB is searched: there is no h
                    // Then A, B are searched. There is no h
                    // Then Y and Z are searched.
                    // lookup finds Y::h and Z::h. Overload resolution picks Z::h(double)
    }

It is allowed for the same declaration to be found more than once:

    namespace A { int a; }
    namespace B { using namespace A; }
    namespace D { using A::a; }
    namespace BD {
      using namespace B;
      using namespace D;
    }
    void g()
    {
      BD::a++; // OK: finds the same A::a through B and through D
    }

| This section is incomplete Reason: the rest of 3.4.3.2[namespace.qual], try to shorten their examples

### [edit] See also

- Unqualified name lookup
- Scope
- Argument-dependent lookup
- Template argument deduction
- Overload resolution

Retrieved from "http://en.cppreference.com/mwiki/index.php?title=cpp/language/qualified_lookup&oldid=80109"
Category:

- Todo with reason