9 Declarations [dcl.dcl]

9.9 The using declaration [namespace.udecl]

The component names of a using-declarator are those of its nested-name-specifier and unqualified-id.
Each using-declarator in a using-declaration92 names the set of declarations found by lookup ([basic.lookup.qual]) for the using-declarator, except that class and enumeration declarations that would be discarded are merely ignored when checking for ambiguity ([basic.lookup]), conversion function templates with a dependent return type are ignored, and certain functions are hidden as described below.
If the terminal name of the using-declarator is dependent ([temp.dep.type]), the using-declarator is considered to name a constructor if and only if the nested-name-specifier has a terminal name that is the same as the unqualified-id.
If the lookup in any instantiation finds that a using-declarator that is not considered to name a constructor does do so, or that a using-declarator that is considered to name a constructor does not, the program is ill-formed.
If the using-declarator names a constructor, it declares that the class inherits the named set of constructor declarations from the nominated base class.
[Note 1:
Otherwise, the unqualified-id in the using-declarator is bound to the using-declarator, which is replaced during name lookup with the declarations it names ([basic.lookup]).
If such a declaration is of an enumeration, the names of its enumerators are not bound.
For the keyword typename, see [temp.res].
— end note]
In a using-declaration used as a member-declaration, each using-declarator shall either name an enumerator or have a nested-name-specifier naming a base class of the current class ([expr.prim.this]).
[Example 1: enum class button { up, down }; struct S { using button::up; button b = up; // OK }; — end example]
If a using-declarator names a constructor, its nested-name-specifier shall name a direct base class of the current class.
If the immediate (class) scope is associated with a class template, it shall derive from the specified base class or have at least one dependent base class.
[Example 2: struct B { void f(char); enum E { e }; union { int x; }; }; struct C { int f(); }; struct D : B { using B::f; // OK: B is a base of D 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::f; // error: C isn't a base of D void f(int) { f('c'); } // calls B​::​f(char) void g(int) { g('c'); } // recursively calls D​::​g(int) }; template <typename... bases> struct X : bases... { using bases::f...; }; X<B, C> x; // OK: B​::​f and C​::​f named — end example]
[Note 2:
Since destructors do not have names, a using-declaration cannot refer to a destructor for a base class.
— end note]
If a constructor or assignment operator brought from a base class into a derived class has the signature of a copy/move constructor or assignment operator for the derived class ([class.copy.ctor], [class.copy.assign]), the using-declaration does not by itself suppress the implicit declaration of the derived class member; the member from the base class is hidden or overridden by the implicitly-declared copy/move constructor or assignment operator of the derived class, as described below.
A using-declaration shall not name a template-id.
[Example 3: struct A { template <class T> void f(T); template <class T> struct X { }; }; struct B : A { using A::f<double>; // error using A::X<int>; // error }; — end example]
A using-declaration shall not name a namespace.
A using-declaration that names a class member other than an enumerator shall be a member-declaration.
[Example 4: 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]
If a declaration is named by two using-declarators that inhabit the same class scope, the program is ill-formed.
[Note 3:
A using-declarator whose nested-name-specifier names a namespace does not name declarations added to the namespace after it.
Thus, additional overloads added after the using-declaration are ignored, but default function arguments ([dcl.fct.default]), default template arguments ([temp.param]), and template specializations ([temp.spec.partial], [temp.expl.spec]) are considered.
— end note]
[Example 5: 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]
If a declaration named by a using-declaration that inhabits the target scope of another declaration potentially conflicts with it ([basic.scope.scope]), and either is reachable from the other, the program is ill-formed.
If two declarations named by using-declarations that inhabit the same scope potentially conflict, either is reachable from the other, and they do not both declare functions or function templates, the program is ill-formed.
[Note 4:
Overload resolution possibly cannot distinguish between conflicting function declarations.
— end note]
[Example 6: namespace A { int x; int f(int); int g; void h(); } 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: conflicts void f(char); using B::f; // OK: each f is a function using A::f; // OK, but interferes with B​::​f(int) f(1); // error: ambiguous static_cast<int(*)(int)>(f)(1); // OK: calls A​::​f 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 A::g; // error: conflicts with B​::​g void h(); using A::h; // error: conflicts 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]
The set of declarations named by a using-declarator that inhabits a class C does not include member functions and member function templates of a base class that correspond to (and thus would conflict with) a declaration of a function or function template in C.
[Example 7: 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) } struct B1 { B1(int); }; struct B2 { B2(int); }; struct D1 : B1, B2 { using B1::B1; using B2::B2; }; D1 d1(0); // error: ambiguous struct D2 : B1, B2 { using B1::B1; using B2::B2; D2(int); // OK: D2​::​D2(int) hides B1​::​B1(int) and B2​::​B2(int) }; D2 d2(0); // calls D2​::​D2(int) — end example]
[Note 5:
For the purpose of forming a set of candidates during overload resolution, the functions named by a using-declaration in a derived class are treated as though they were direct members of the derived class.
In particular, the implicit object parameter is treated as if it were a reference to the derived class rather than to the base class ([over.match.funcs]).
This has no effect on the type of the function, and in all other respects the function remains part of the base class.
— end note]
Constructors that are named by a using-declaration are treated as though they were constructors of the derived class when looking up the constructors of the derived class ([class.qual]) or forming a set of overload candidates ([over.match.ctor], [over.match.copy], [over.match.list]).
[Note 6:
If such a constructor is selected to perform the initialization of an object of class type, all subobjects other than the base class from which the constructor originated are implicitly initialized ([class.inhctor.init]).
A constructor of a derived class is sometimes preferred to a constructor of a base class if they would otherwise be ambiguous ([over.match.best]).
— end note]
In a using-declarator that does not name a constructor, every declaration named shall be accessible.
In a using-declarator that names a constructor, no access check is performed.
[Note 7:
Because a using-declarator designates a base class member (and not a member subobject or a member function of a base class subobject), a using-declarator cannot be used to resolve inherited member ambiguities.
[Example 8: 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(); // error: overload resolution selects A​::​x, but A is an ambiguous base class } — end example]
— end note]
A using-declaration has the usual accessibility for a member-declaration.
Base-class constructors considered because of a using-declarator are accessible if they would be accessible when used to construct an object of the base class; the accessibility of the using-declaration is ignored.
[Example 9: 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]
92)92)
A using-declaration with more than one using-declarator is equivalent to a corresponding sequence of using-declarations with one using-declarator each.