[namespace.udecl] (original) (raw)

9 Declarations [dcl.dcl]

9.9 The using declaration [namespace.udecl]

Each using-declarator in a using-declaration85names 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 lookup in any instantiation finds that a using-declaratorthat is not considered to name a constructor does do so, or that a using-declaratorthat 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-declaratoris 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.

— _end note_]

[Example 1: enum class button { up, down };struct S { using button::up; button b = up; }; — _end example_]

If ausing-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; using B::e; using B::x; using C::f; void f(int) { f('c'); } void g(int) { g('c'); } };template <typename... bases> struct X : bases... { using bases::f...;}; X<B, C> x; — _end example_]

[Note 2:

Since destructors do not have names, ausing-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.

[Example 3: struct A { template <class T> void f(T);template <class T> struct X { };};struct B : A { using A::f<double>; using A::X<int>; }; — _end example_]

A using-declaration shall not name a namespace.

A using-declaration that names a class member other than an enumerator shall be amember-declaration.

[Example 4: struct X { int i;static int s;};void f() { using X::i; using X::s; } — _end example_]

If a declaration is named by two using-declarator_s_that inhabit the same class scope, the program is ill-formed.

[Example 5: struct C { int i;};struct D1 : C { };struct D2 : C { };struct D3 : D1, D2 { using D1::i; using D1::i; using D2::i; }; — _end example_]

[Note 3:

A using-declaratorwhose nested-name-specifier names a namespace does not name declarations added to the namespace after it.

— _end note_]

[Example 6: namespace A { void f(int);} using A::f; namespace A { void f(char);} void foo() { f('a'); } void bar() { using A::f; f('a'); } — _end example_]

If a declaration named by a using-declarationthat inhabits the target scope of another declaration Bpotentially conflicts with it ([basic.scope.scope]), and either is reachable from the other, the program is ill-formed unless B is name-independent and the using-declaration precedes B.

[Example 7: int _;void f() { int _; _ = 0;using ::_; } — _end example_]

If two declarations named by using-declaration_s_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 8: 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); } void func() { int i;using B::i; void f(char);using B::f; using A::f; f(1); static_cast<int(*)(int)>(f)(1); f(3.5); using B::g; g('a'); struct g g1; using A::g; void h();using A::h; using B::x;using A::x; using A::x; x = 99; struct x x1; } — _end example_]

The set of declarations named by a using-declaratorthat 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 9: 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); using B::g;void g(char); using B::h;void h(int); };void k(D* p) { p->f(1); p->f('a'); p->g(1); p->g('a'); } struct B1 { B1(int);};struct B2 { B2(int);};struct D1 : B1, B2 { using B1::B1;using B2::B2;}; D1 d1(0); struct D2 : B1, B2 { using B1::B1;using B2::B2; D2(int); }; D2 d2(0); — _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-declarationare 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 10: 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(); } — _end example_]

— _end note_]

Base-class constructors considered because of a using-declaratorare 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 11: class A { private: void f(char);public: void f(int);protected: void g();};class B : public A { using A::f; public: using A::g; }; — _end example_]