Files
cppdraft_translate/cppdraft/namespace/udecl.md
2025-10-25 03:02:53 +03:00

301 lines
19 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[namespace.udecl]
# 9 Declarations [[dcl]](./#dcl)
## 9.10 The using declaration [namespace.udecl]
[using-declaration:](#nt:using-declaration "9.10The using declaration[namespace.udecl]")
using [*using-declarator-list*](#nt:using-declarator-list "9.10The using declaration[namespace.udecl]") ;
[using-declarator-list:](#nt:using-declarator-list "9.10The using declaration[namespace.udecl]")
[*using-declarator*](#nt:using-declarator "9.10The using declaration[namespace.udecl]") ...opt
[*using-declarator-list*](#nt:using-declarator-list "9.10The using declaration[namespace.udecl]") , [*using-declarator*](#nt:using-declarator "9.10The using declaration[namespace.udecl]") ...opt
[using-declarator:](#nt:using-declarator "9.10The using declaration[namespace.udecl]")
typenameopt [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified 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.10The using declaration[namespace.udecl]") are those
of its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") and [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]")[.](#1.sentence-1)
Each [*using-declarator*](#nt:using-declarator "9.10The using declaration[namespace.udecl]") in a [*using-declaration*](#nt:using-declaration "9.10The 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.5Qualified name lookup"))
for the [*using-declarator*](#nt:using-declarator "9.10The 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.5Name 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.10The using declaration[namespace.udecl]") is dependent ([[temp.dep.type]](temp.dep.type "13.8.3.2Dependent types")),
the [*using-declarator*](#nt:using-declarator "9.10The 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.3Qualified 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.2Unqualified names[expr.prim.id.unqual]")[.](#1.sentence-3)
If the lookup in any instantiation finds
that a [*using-declarator*](#nt:using-declarator "9.10The using declaration[namespace.udecl]") that is not considered to name a constructor does do so, or
that a [*using-declarator*](#nt:using-declarator "9.10The 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.10The using declaration[namespace.udecl]") names a constructor,
it declares that the class [*inherits*](#def:constructor,inherited "9.10The 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.2Unqualified names[expr.prim.id.unqual]") in the [*using-declarator*](#nt:using-declarator "9.10The using declaration[namespace.udecl]") is bound to the [*using-declarator*](#nt:using-declarator "9.10The using declaration[namespace.udecl]"),
which is replaced during name lookup
with the declarations it names ([[basic.lookup]](basic.lookup "6.5Name 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.8Name 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.10The using declaration[namespace.udecl]") used as a[*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]"),
each [*using-declarator*](#nt:using-declarator "9.10The 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.3Qualified names[expr.prim.id.qual]") naming a base class of the current class ([[expr.prim.this]](expr.prim.this "7.5.3This"))[.](#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.10The using declaration[namespace.udecl]") names a constructor,
its [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified 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.10The 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.3Copy/move constructors"), [[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator")),
the [*using-declaration*](#nt:using-declaration "9.10The 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.10The using declaration[namespace.udecl]") shall not name a [*template-id*](temp.names#nt:template-id "13.3Names 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.10The 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.10The 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.1General[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.10The 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.10The using declaration[namespace.udecl]") whose [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified 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.10The using declaration[namespace.udecl]") are ignored, but
default function arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments")), default template
arguments ([[temp.param]](temp.param "13.2Template parameters")), and
template specializations ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization"), [[temp.expl.spec]](temp.expl.spec "13.9.4Explicit 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.10The 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.1General")), 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.10The 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.10The using declaration[namespace.udecl]") does not precede B} — *end example*]
If two declarations named by [*using-declaration*](#nt:using-declaration "9.10The 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.10The 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.10The 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.2Candidate 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.10The 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.2Class members"))
or forming a set of overload candidates ([[over.match.ctor]](over.match.ctor "12.2.2.4Initialization by constructor"), [[over.match.copy]](over.match.copy "12.2.2.5Copy-initialization of class by user-defined conversion"), [[over.match.list]](over.match.list "12.2.2.8Initialization 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.4Initialization 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.4Best 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.10The 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.10The 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.10The 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.10The 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.10The using declaration[namespace.udecl]") has the usual
accessibility for a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]")[.](#16.sentence-1)
Base-class constructors considered because of a [*using-declarator*](#nt:using-declarator "9.10The 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.10The 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.10The using declaration[namespace.udecl]") with more than one[*using-declarator*](#nt:using-declarator "9.10The using declaration[namespace.udecl]") is equivalent to a corresponding sequence
of [*using-declaration*](#nt:using-declaration "9.10The using declaration[namespace.udecl]")*s* with
one [*using-declarator*](#nt:using-declarator "9.10The using declaration[namespace.udecl]") each[.](#footnote-84.sentence-1)