3 Basic concepts [basic]

3.4 Name lookup [basic.lookup]

3.4.1 Unqualified name lookup [basic.lookup.unqual]

In all the cases listed in [basic.lookup.unqual], the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. If no declaration is found, the program is ill-formed.

The declarations from the namespace nominated by a using-directive become visible in a namespace enclosing the using-directive; see [namespace.udir]. For the purpose of the unqualified name lookup rules described in [basic.lookup.unqual], the declarations from the namespace nominated by the using-directive are considered members of that enclosing namespace.

The lookup for an unqualified name used as the postfix-expression of a function call is described in [basic.lookup.argdep]. [ Note: For purposes of determining (during parsing) whether an expression is a postfix-expression for a function call, the usual name lookup rules apply. The rules in [basic.lookup.argdep] have no effect on the syntactic interpretation of an expression. For example,

typedef int f;
namespace N {
  struct A {
    friend void f(A &);
    operator int();
    void g(A a) {
      int i = f(a);         // f is the typedef, not the friend
                            // function: equivalent to int(a)
    }
  };
}

Because the expression is not a function call, the argument-dependent name lookup ([basic.lookup.argdep]) does not apply and the friend function f is not found.  — end note ]

A name used in global scope, outside of any function, class or user-declared namespace, shall be declared before its use in global scope.

A name used in a user-declared namespace outside of the definition of any function or class shall be declared before its use in that namespace or before its use in a namespace enclosing its namespace.

A name used in the definition of a function following the function's declarator-id28 that is a member of namespace N (where, only for the purpose of exposition, N could represent the global scope) shall be declared before its use in the block in which it is used or in one of its enclosing blocks ([stmt.block]) or, shall be declared before its use in namespace N or, if N is a nested namespace, shall be declared before its use in one of N's enclosing namespaces. [ Example:

namespace A {
  namespace N {
    void f();
  }
}
void A::N::f() {
  i = 5;
  // The following scopes are searched for a declaration of i:
  // 1) outermost block scope of A::N::f, before the use of i
  // 2) scope of namespace N
  // 3) scope of namespace A
  // 4) global scope, before the definition of A::N::f
}

 — end example ]

A name used in the definition of a class X outside of a member function body, default argument, exception-specification, brace-or-equal-initializer of a non-static data member, or nested class definition29 shall be declared in one of the following ways:

  • before its use in class X or be a member of a base class of X ([class.member.lookup]), or

  • if X is a nested class of class Y ([class.nest]), before the definition of X in Y, or shall be a member of a base class of Y (this lookup applies in turn to Y 's enclosing classes, starting with the innermost enclosing class),30 or

  • if X is a local class ([class.local]) or is a nested class of a local class, before the definition of class X in a block enclosing the definition of class X, or

  • if X is a member of namespace N, or is a nested class of a class that is a member of N, or is a local class or a nested class within a local class of a function that is a member of N, before the definition of class X in namespace N or in one of N 's enclosing namespaces.

Example:

namespace M {
  class B { };
}

namespace N {
  class Y : public M::B {
    class X {
      int a[i];
    };
  };
}

// The following scopes are searched for a declaration of i:
// 1) scope of class N::Y::X, before the use of i
// 2) scope of class N::Y, before the definition of N::Y::X
// 3) scope of N::Y's base class M::B
// 4) scope of namespace N, before the definition of N::Y
// 5) global scope, before the definition of N

 — end example ] [ Note: When looking for a prior declaration of a class or function introduced by a friend declaration, scopes outside of the innermost enclosing namespace scope are not considered; see [namespace.memdef].  — end note ] [ Note: [basic.scope.class] further describes the restrictions on the use of names in a class definition. [class.nest] further describes the restrictions on the use of names in nested class definitions. [class.local] further describes the restrictions on the use of names in local class definitions.  — end note ]

For the members of a class X, a name used in a member function body, in a default argument, in an exception-specification, in the brace-or-equal-initializer of a non-static data member ([class.mem]), or in the definition of a class member outside of the definition of X, following the member's declarator-id31, shall be declared in one of the following ways:

  • before its use in the block in which it is used or in an enclosing block ([stmt.block]), or

  • shall be a member of class X or be a member of a base class of X ([class.member.lookup]), or

  • if X is a nested class of class Y ([class.nest]), shall be a member of Y, or shall be a member of a base class of Y (this lookup applies in turn to Y's enclosing classes, starting with the innermost enclosing class),32 or

  • if X is a local class ([class.local]) or is a nested class of a local class, before the definition of class X in a block enclosing the definition of class X, or

  • if X is a member of namespace N, or is a nested class of a class that is a member of N, or is a local class or a nested class within a local class of a function that is a member of N, before the use of the name, in namespace N or in one of N 's enclosing namespaces.

Example:

class B { };
namespace M {
  namespace N {
    class X : public B {
      void f();
    };
  }
}
void M::N::X::f() {
  i = 16;
}

// The following scopes are searched for a declaration of i:
// 1) outermost block scope of M::N::X::f, before the use of i
// 2) scope of class M::N::X
// 3) scope of M::N::X's base class B
// 4) scope of namespace M::N
// 5) scope of namespace M
// 6) global scope, before the definition of M::N::X::f

 — end example ] [ Note: [class.mfct] and [class.static] further describe the restrictions on the use of names in member function definitions. [class.nest] further describes the restrictions on the use of names in the scope of nested classes. [class.local] further describes the restrictions on the use of names in local class definitions.  — end note ]

Name lookup for a name used in the definition of a friend function ([class.friend]) defined inline in the class granting friendship shall proceed as described for lookup in member function definitions. If the friend function is not defined in the class granting friendship, name lookup in the friend function definition shall proceed as described for lookup in namespace member function definitions.

In a friend declaration naming a member function, a name used in the function declarator and not part of a template-argument in the declarator-id is first looked up in the scope of the member function's class ([class.member.lookup]). If it is not found, or if the name is part of a template-argument in the declarator-id, the look up is as described for unqualified names in the definition of the class granting friendship. [ Example:

struct A {
  typedef int AT;
  void f1(AT);
  void f2(float);
  template <class T> void f3();
};
struct B {
  typedef char AT;
  typedef float BT;
  friend void A::f1(AT);      // parameter type is A::AT
  friend void A::f2(BT);      // parameter type is B::BT
  friend void A::f3<AT>();    // template argument is B::AT
};

 — end example ]

During the lookup for a name used as a default argument ([dcl.fct.default]) in a function parameter-declaration-clause or used in the expression of a mem-initializer for a constructor ([class.base.init]), the function parameter names are visible and hide the names of entities declared in the block, class or namespace scopes containing the function declaration. [ Note: [dcl.fct.default] further describes the restrictions on the use of names in default arguments. [class.base.init] further describes the restrictions on the use of names in a ctor-initializer.  — end note ]

During the lookup of a name used in the constant-expression of an enumerator-definition, previously declared enumerators of the enumeration are visible and hide the names of entities declared in the block, class, or namespace scopes containing the enum-specifier.

A name used in the definition of a static data member of class X ([class.static.data]) (after the qualified-id of the static member) is looked up as if the name was used in a member function of X. [ Note: [class.static.data] further describes the restrictions on the use of names in the definition of a static data member.  — end note ]

If a variable member of a namespace is defined outside of the scope of its namespace then any name that appears in the definition of the member (after the declarator-id) is looked up as if the definition of the member occurred in its namespace. [ Example:

namespace N {
  int i = 4;
  extern int j;
}

int i = 2;

int N::j = i;                   // N::j == 4

 — end example ]

A name used in the handler for a function-try-block (Clause [except]) is looked up as if the name was used in the outermost block of the function definition. In particular, the function parameter names shall not be redeclared in the exception-declaration nor in the outermost block of a handler for the function-try-block. Names declared in the outermost block of the function definition are not found when looked up in the scope of a handler for the function-try-block. [ Note: But function parameter names are found.  — end note ]

Note: The rules for name lookup in template definitions are described in [temp.res].  — end note ]

This refers to unqualified names that occur, for instance, in a type or default argument in the parameter-declaration-clause or used in the function body.

This refers to unqualified names following the class name; such a name may be used in the base-clause or may be used in the class definition.

This lookup applies whether the definition of X is nested within Y's definition or whether X's definition appears in a namespace scope enclosing Y 's definition ([class.nest]).

That is, an unqualified name that occurs, for instance, in a type in the parameter-declaration-clause or in the exception-specification.

This lookup applies whether the member function is defined within the definition of class X or whether the member function is defined in a namespace scope enclosing X's definition.