301 lines
19 KiB
Markdown
301 lines
19 KiB
Markdown
[namespace.udecl]
|
||
|
||
# 9 Declarations [[dcl]](./#dcl)
|
||
|
||
## 9.10 The using declaration [namespace.udecl]
|
||
|
||
[using-declaration:](#nt:using-declaration "9.10 The using declaration [namespace.udecl]")
|
||
using [*using-declarator-list*](#nt:using-declarator-list "9.10 The using declaration [namespace.udecl]") ;
|
||
|
||
[using-declarator-list:](#nt:using-declarator-list "9.10 The using declaration [namespace.udecl]")
|
||
[*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ...opt
|
||
[*using-declarator-list*](#nt:using-declarator-list "9.10 The using declaration [namespace.udecl]") , [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ...opt
|
||
|
||
[using-declarator:](#nt:using-declarator "9.10 The using declaration [namespace.udecl]")
|
||
typenameopt [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]")
|
||
|
||
[1](#1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8687)
|
||
|
||
The component names of a [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") are those
|
||
of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") and [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]")[.](#1.sentence-1)
|
||
|
||
Each [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") in a [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]")[84](#footnote-84 "A using-declaration with more than one using-declarator is equivalent to a corresponding sequence of using-declarations with one using-declarator each.") names the set of declarations found by lookup ([[basic.lookup.qual]](basic.lookup.qual "6.5.5 Qualified name lookup"))
|
||
for the [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]"),
|
||
except that class and enumeration declarations that would be discarded
|
||
are merely ignored when checking for ambiguity ([[basic.lookup]](basic.lookup "6.5 Name lookup")),
|
||
conversion function templates with a dependent return type are ignored, and
|
||
certain functions are hidden as described below[.](#1.sentence-2)
|
||
|
||
If the terminal name of the [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") is dependent ([[temp.dep.type]](temp.dep.type "13.8.3.2 Dependent types")),
|
||
the [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") is considered to name a constructor
|
||
if and only if the [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") has a terminal name
|
||
that is the same as the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]")[.](#1.sentence-3)
|
||
|
||
If the lookup in any instantiation finds
|
||
that a [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") that is not considered to name a constructor does do so, or
|
||
that a [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") that is considered to name a constructor does not,
|
||
the program is ill-formed[.](#1.sentence-4)
|
||
|
||
[2](#2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8716)
|
||
|
||
If the [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") names a constructor,
|
||
it declares that the class [*inherits*](#def:constructor,inherited "9.10 The using declaration [namespace.udecl]") the named set of constructor declarations
|
||
from the nominated base class[.](#2.sentence-1)
|
||
|
||
[*Note [1](#note-1)*:
|
||
|
||
Otherwise,
|
||
the [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") in the [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") is bound to the [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]"),
|
||
which is replaced during name lookup
|
||
with the declarations it names ([[basic.lookup]](basic.lookup "6.5 Name lookup"))[.](#2.sentence-2)
|
||
|
||
If such a declaration is of an enumeration,
|
||
the names of its enumerators are not bound[.](#2.sentence-3)
|
||
|
||
For the keyword typename, see [[temp.res]](temp.res "13.8 Name resolution")[.](#2.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[3](#3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8732)
|
||
|
||
In a [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") used as a[*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]"),
|
||
each [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") shall either name an enumerator
|
||
or have a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") naming a base class of the current class ([[expr.prim.this]](expr.prim.this "7.5.3 This"))[.](#3.sentence-1)
|
||
|
||
[*Example [1](#example-1)*: enum class button { up, down };struct S {using button::up;
|
||
button b = up; // OK}; â *end example*]
|
||
|
||
If a[*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") names a constructor,
|
||
its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") shall name
|
||
a direct base class of the current class[.](#3.sentence-2)
|
||
|
||
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[.](#3.sentence-3)
|
||
|
||
[*Example [2](#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 Dusing B::e; // OK, e is an enumerator of base Busing B::x; // OK, x is a union member of base Busing C::f; // error: C isn't a base of Dvoid 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*]
|
||
|
||
[4](#4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8783)
|
||
|
||
[*Note [2](#note-2)*:
|
||
|
||
Since destructors do not have names, a[*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") cannot refer to a
|
||
destructor for a base class[.](#4.sentence-1)
|
||
|
||
â *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.ctor "11.4.5.3 Copy/move constructors"), [[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator")),
|
||
the [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") 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[.](#4.sentence-2)
|
||
|
||
[5](#5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8798)
|
||
|
||
A [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") shall not name a [*template-id*](temp.names#nt:template-id "13.3 Names of template specializations [temp.names]")[.](#5.sentence-1)
|
||
|
||
[*Example [3](#example-3)*: struct A {template <class T> void f(T); template <class T> struct X { };};struct B : A {using A::f<double>; // errorusing A::X<int>; // error}; â *end example*]
|
||
|
||
[6](#6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8813)
|
||
|
||
A [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") shall not name a namespace[.](#6.sentence-1)
|
||
|
||
[7](#7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8816)
|
||
|
||
A [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") that names a class member
|
||
other than an enumerator
|
||
shall be a[*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]")[.](#7.sentence-1)
|
||
|
||
[*Example [4](#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*]
|
||
|
||
[8](#8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8835)
|
||
|
||
If a declaration is named by two [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]")*s* that inhabit the same class scope, the program is ill-formed[.](#8.sentence-1)
|
||
|
||
[*Example [5](#example-5)*: struct C {int i;};
|
||
|
||
struct D1 : C { };struct D2 : C { };
|
||
|
||
struct D3 : D1, D2 {using D1::i; // OK, equivalent to using C::iusing D1::i; // error: duplicateusing D2::i; // error: duplicate, also names C::i}; â *end example*]
|
||
|
||
[9](#9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8855)
|
||
|
||
[*Note [3](#note-3)*:
|
||
|
||
A [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") whose [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") names a namespace
|
||
does not name declarations added to the namespace after it[.](#9.sentence-1)
|
||
|
||
Thus, additional
|
||
overloads added after the [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") are ignored, but
|
||
default function arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments")), default template
|
||
arguments ([[temp.param]](temp.param "13.2 Template parameters")), and
|
||
template specializations ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial specialization"), [[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")) are considered[.](#9.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [6](#example-6)*: 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*]
|
||
|
||
[10](#10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8887)
|
||
|
||
If a declaration named by a [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") that inhabits the target scope of another declaration B potentially conflicts with it ([[basic.scope.scope]](basic.scope.scope "6.4.1 General")), and
|
||
either is reachable from the other, the program is ill-formed
|
||
unless B is name-independent and
|
||
the [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") precedes B[.](#10.sentence-1)
|
||
|
||
[*Example [7](#example-7)*: int _;void f() {int _; // B _ = 0; using ::_; // error: [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") does not precede B} â *end example*]
|
||
|
||
If two declarations named by [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*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[.](#10.sentence-2)
|
||
|
||
[*Note [4](#note-4)*:
|
||
|
||
Overload resolution possibly cannot distinguish
|
||
between conflicting function declarations[.](#10.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [8](#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); // OK, hides struct g}void func() {int i; using B::i; // error: conflictsvoid f(char); using B::f; // OK, each f is a functionusing A::f; // OK, but interferes with B::f(int) f(1); // error: ambiguousstatic_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::gusing A::g; // error: conflicts with B::gvoid h(); using A::h; // error: conflictsusing B::x; using A::x; // OK, hides struct B::xusing A::x; // OK, does not conflict with previous using A::x x = 99; // assigns to A::xstruct x x1; // x1 has class type B::x} â *end example*]
|
||
|
||
[11](#11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L8955)
|
||
|
||
The set of declarations named by a [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") 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[.](#11.sentence-1)
|
||
|
||
[*Example [9](#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); // OK, D::f(int) overrides B::f(int);using B::g; void g(char); // OKusing 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: ambiguousstruct 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*]
|
||
|
||
[12](#12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9013)
|
||
|
||
[*Note [5](#note-5)*:
|
||
|
||
For the purpose of forming a set of candidates during overload resolution,
|
||
the functions
|
||
named by a [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") in a derived class
|
||
are treated as though they were direct members of the derived class[.](#12.sentence-1)
|
||
|
||
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]](over.match.funcs "12.2.2 Candidate functions and argument lists"))[.](#12.sentence-2)
|
||
|
||
This has no effect on the type of the function, and in all other
|
||
respects the function remains part of the base class[.](#12.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[13](#13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9026)
|
||
|
||
Constructors that are named by a [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") are treated as though they were constructors of the derived class
|
||
when looking up the constructors of the derived class ([[class.qual]](class.qual "6.5.5.2 Class members"))
|
||
or forming a set of overload candidates ([[over.match.ctor]](over.match.ctor "12.2.2.4 Initialization by constructor"), [[over.match.copy]](over.match.copy "12.2.2.5 Copy-initialization of class by user-defined conversion"), [[over.match.list]](over.match.list "12.2.2.8 Initialization by list-initialization"))[.](#13.sentence-1)
|
||
|
||
[*Note [6](#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]](class.inhctor.init "11.9.4 Initialization by inherited constructor"))[.](#13.sentence-2)
|
||
|
||
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]](over.match.best "12.2.4 Best viable function"))[.](#13.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[14](#14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9040)
|
||
|
||
In a [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") that does not name a constructor,
|
||
every declaration named shall be accessible[.](#14.sentence-1)
|
||
|
||
In a [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") that names a constructor,
|
||
no access check is performed[.](#14.sentence-2)
|
||
|
||
[15](#15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9047)
|
||
|
||
[*Note [7](#note-7)*:
|
||
|
||
Because a [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") designates a base class member
|
||
(and not a member subobject or a member function of a base class
|
||
subobject), a [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") cannot be used to resolve
|
||
inherited member ambiguities[.](#15.sentence-1)
|
||
|
||
[*Example [10](#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(); // error: overload resolution selects A::x, but A is an ambiguous base class} â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[16](#16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L9073)
|
||
|
||
A [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") has the usual
|
||
accessibility for a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]")[.](#16.sentence-1)
|
||
|
||
Base-class constructors considered because of a [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") are accessible if they would be accessible
|
||
when used to construct an object of the base class;
|
||
the accessibility of the [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") is ignored[.](#16.sentence-2)
|
||
|
||
[*Example [11](#example-11)*: 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 inaccessiblepublic:using A::g; // B::g is a public synonym for A::g}; â *end example*]
|
||
|
||
[84)](#footnote-84)[84)](#footnoteref-84)
|
||
|
||
A [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]") with more than one[*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") is equivalent to a corresponding sequence
|
||
of [*using-declaration*](#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*s* with
|
||
one [*using-declarator*](#nt:using-declarator "9.10 The using declaration [namespace.udecl]") each[.](#footnote-84.sentence-1)
|