7 Declarations [dcl.dcl]

7.3 Namespaces [basic.namespace]

7.3.3 The using declaration [namespace.udecl]

A using-declaration introduces a name into the declarative region in which the using-declaration appears.

using-declaration:
    using typenameopt nested-name-specifier unqualified-id ;
    using :: unqualified-id ;

The member name specified in a using-declaration is declared in the declarative region in which the using-declaration appears. [ Note: Only the specified name is so declared; specifying an enumeration name in a using-declaration does not declare its enumerators in the using-declaration's declarative region.  — end note ] If a using-declaration names a constructor ([class.qual]), it implicitly declares a set of constructors in the class in which the using-declaration appears ([class.inhctor]); otherwise the name specified in a using-declaration is a synonym for the name of some entity declared elsewhere.

Every using-declaration is a declaration and a member-declaration and so can be used in a class definition. [ Example:

struct B {
  void f(char);
  void g(char);
  enum E { e };
  union { int x; };
};

struct D : B {
  using B::f;
  void f(int) { f('c'); }       // calls B::f(char)
  void g(int) { g('c'); }       // recursively calls D::g(int)
};

 — end example ]

In a using-declaration used as a member-declaration, the nested-name-specifier shall name a base class of the class being defined. If such a using-declaration names a constructor, the nested-name-specifier shall name a direct base class of the class being defined; otherwise it introduces the set of declarations found by member name lookup ([class.member.lookup], [class.qual]). [ Example:

class C {
  int g();
};

class D2 : public B {
  using B::f;                   // OK: B is a base of D2
  using B::e;                   // OK: e is an enumerator of base B
  using B::x;                   // OK: x is a union member of base B
  using C::g;                   // error: C isn't a base of D2
};

 — end example ]

Note: Since destructors do not have names, a using-declaration cannot refer to a destructor for a base class. Since specializations of member templates for conversion functions are not found by name lookup, they are not considered when a using-declaration specifies a conversion function ([temp.mem]).  — end note ] If an assignment operator brought from a base class into a derived class scope has the signature of a copy/move assignment operator for the derived class ([class.copy]), the using-declaration does not by itself suppress the implicit declaration of the derived class assignment operator; the copy/move assignment operator from the base class is hidden or overridden by the implicitly-declared copy/move assignment operator of the derived class, as described below.

A using-declaration shall not name a template-id. [ Example:

struct A {
  template <class T> void f(T);
  template <class T> struct X { };
};
struct B : A {
  using A::f<double>;           // ill-formed
  using A::X<int>;              // ill-formed
};

 — end example ]

A using-declaration shall not name a namespace.

A using-declaration shall not name a scoped enumerator.

A using-declaration for a class member shall be a member-declaration. [ Example:

struct X {
  int i;
  static int s;
};

void f() {
  using X::i;       // error: X::i is a class member
                    // and this is not a member declaration.
  using X::s;       // error: X::s is a class member
                    // and this is not a member declaration.
}

 — end example ]

Members declared by a using-declaration can be referred to by explicit qualification just like other member names ([namespace.qual]). In a using-declaration, a prefix :: refers to the global namespace. [ Example:

void f();

namespace A {
  void g();
}

namespace X {
  using ::f;        // global f
  using A::g;       // A's g
}

void h(){
  X::f();           // calls ::f
  X::g();           // calls A::g
}

 — end example ]

A using-declaration is a declaration and can therefore be used repeatedly where (and only where) multiple declarations are allowed. [ Example:

namespace A {
  int i;
}

namespace A1 {
  using A::i;
  using A::i;       // OK: double declaration
}

void f() {
  using A::i;
  using A::i;       // error: double declaration
}

struct B {
  int i;
};

struct X : B {
  using B::i;
  using B::i;       // error: double member declaration
};

 — end example ]

The entity declared by a using-declaration shall be known in the context using it according to its definition at the point of the using-declaration. Definitions added to the namespace after the using-declaration are not considered when a use of the name is made. [ Example:

namespace A {
  void f(int);
}

using A::f;         // f is a synonym for A::f;
                    // that is, for A::f(int).
namespace A {
  void f(char);
}

void foo() {
  f('a');           // calls f(int),
}                   // even though f(char) exists.

void bar() {
  using A::f;       // f is a synonym for A::f;
                    // that is, for A::f(int) and A::f(char).
  f('a');           // calls f(char)
}

 — end example ]

Note: Partial specializations of class templates are found by looking up the primary class template and then considering all partial specializations of that template. If a using-declaration names a class template, partial specializations introduced after the using-declaration are effectively visible because the primary template is visible ([temp.class.spec]).  — end note ]

Since a using-declaration is a declaration, the restrictions on declarations of the same name in the same declarative region ([basic.scope]) also apply to using-declarations. [ Example:

namespace A {
  int x;
}

namespace B {
  int i;
  struct g { };
  struct x { };
  void f(int);
  void f(double);
  void g(char);     // OK: hides struct g
}

void func() {
  int i;
  using B::i;       // error: i declared twice
  void f(char);
  using B::f;       // OK: each f is a function
  f(3.5);           // calls B::f(double)
  using B::g;
  g('a');           // calls B::g(char)
  struct g g1;      // g1 has class type B::g
  using B::x;
  using A::x;       // OK: hides struct B::x
  x = 99;           // assigns to A::x
  struct x x1;      // x1 has class type B::x
}

 — end example ]

If a function declaration in namespace scope or block scope has the same name and the same parameter types as a function introduced by a using-declaration, and the declarations do not declare the same function, the program is ill-formed. [ Note: Two using-declarations may introduce functions with the same name and the same parameter types. If, for a call to an unqualified function name, function overload resolution selects the functions introduced by such using-declarations, the function call is ill-formed. [ Example:

namespace B {
  void f(int);
  void f(double);
}
namespace C {
  void f(int);
  void f(double);
  void f(char);
}

void h() {
  using B::f;       // B::f(int) and B::f(double)
  using C::f;       // C::f(int), C::f(double), and C::f(char)
  f('h');           // calls C::f(char)
  f(1);             // error: ambiguous: B::f(int) or C::f(int)?
  void f(int);      // error: f(int) conflicts with C::f(int) and B::f(int)
}

 — end example ]  — end note ]

When a using-declaration brings names from a base class into a derived class scope, member functions and member function templates in the derived class override and/or hide member functions and member function templates with the same name, parameter-type-list ([dcl.fct]), cv-qualification, and ref-qualifier (if any) in a base class (rather than conflicting). [ Note: For using-declarations that name a constructor, see [class.inhctor].  — end note ] [ Example:

struct B {
  virtual void f(int);
  virtual void f(char);
  void g(int);
  void h(int);
};

struct D : B {
  using B::f;
  void f(int);      // OK: D::f(int) overrides B::f(int);

  using B::g;
  void g(char);     // OK

  using B::h;
  void h(int);      // OK: D::h(int) hides B::h(int)
};

void k(D* p){
  p->f(1);          // calls D::f(int)
  p->f('a');        // calls B::f(char)
  p->g(1);          // calls B::g(int)
  p->g('a');        // calls D::g(char)
}

 — end example ]

For the purpose of overload resolution, the functions which are introduced by a using-declaration into a derived class will be treated as though they were members of the derived class. In particular, the implicit this parameter shall be treated as if it were a pointer to the derived class rather than to the base class. This has no effect on the type of the function, and in all other respects the function remains a member of the base class.

The access rules for inheriting constructors are specified in [class.inhctor]; otherwise all instances of the name mentioned in a using-declaration shall be accessible. In particular, if a derived class uses a using-declaration to access a member of a base class, the member name shall be accessible. If the name is that of an overloaded member function, then all functions named shall be accessible. The base class members mentioned by a using-declaration shall be visible in the scope of at least one of the direct base classes of the class where the using-declaration is specified. [ Note: Because a using-declaration designates a base class member (and not a member subobject or a member function of a base class subobject), a using-declaration cannot be used to resolve inherited member ambiguities. For example,

struct A { int x(); };
struct B : A { };
struct C : A {
  using A::x;
  int x(int);
};

struct D : B, C {
  using C::x;
  int x(double);
};
int f(D* d) {
  return d->x();    // ambiguous: B::x or C::x
}

 — end note ]

The alias created by the using-declaration has the usual accessibility for a member-declaration. [ Note: A using-declaration that names a constructor does not create aliases; see [class.inhctor] for the pertinent accessibility rules.  — end note ] [ Example:

class A {
private:
    void f(char);
public:
    void f(int);
protected:
    void g();
};

class B : public A {
  using A::f;       // error: A::f(char) is inaccessible
public:
  using A::g;       // B::g is a public synonym for A::g
};

 — end example ]

If a using-declaration uses the keyword typename and specifies a dependent name ([temp.dep]), the name introduced by the using-declaration is treated as a typedef-name ([dcl.typedef]).