This commit is contained in:
2025-10-25 03:02:53 +03:00
commit 043225d523
3416 changed files with 681196 additions and 0 deletions

117
cppdraft/class/abstract.md Normal file
View File

@@ -0,0 +1,117 @@
[class.abstract]
# 11 Classes [[class]](./#class)
## 11.7 Derived classes [[class.derived]](class.derived#class.abstract)
### 11.7.4 Abstract classes [class.abstract]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4199)
[*Note [1](#note-1)*:
The abstract class mechanism supports the notion of a general concept,
such as a shape, of which only more concrete variants, such ascircle and square, can actually be used[.](#1.sentence-1)
An abstract
class can also be used to define an interface for which derived classes
provide a variety of implementations[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4208)
A virtual function is specified as
a [*pure virtual function*](#def:function,virtual,pure "11.7.4Abstract classes[class.abstract]") by using a[*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1General[class.mem.general]") ([[class.mem]](class.mem "11.4Class members")) in the function declaration
in the class definition[.](#2.sentence-1)
[*Note [2](#note-2)*:
Such a function might be inherited: see below[.](#2.sentence-2)
— *end note*]
A class is an [*abstract class*](#def:class,abstract "11.7.4Abstract classes[class.abstract]") if it has at least one pure virtual function[.](#2.sentence-3)
[*Note [3](#note-3)*:
An abstract class can be used only as a base class of some other class;
no objects of an abstract class can be created
except as subobjects of a class
derived from it ([[basic.def]](basic.def "6.2Declarations and definitions"), [[class.mem]](class.mem "11.4Class members"))[.](#2.sentence-4)
— *end note*]
A pure virtual function need be defined only if called with, or as if
with ([[class.dtor]](class.dtor "11.4.7Destructors")), the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") syntax ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names"))[.](#2.sentence-5)
[*Example [1](#example-1)*: class point { /* ... */ };class shape { // abstract class point center;public: point where() { return center; }void move(point p) { center=p; draw(); }virtual void rotate(int) = 0; // pure virtualvirtual void draw() = 0; // pure virtual}; — *end example*]
[*Note [4](#note-4)*:
A function declaration cannot provide both a [*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1General[class.mem.general]") and a definition[.](#2.sentence-6)
— *end note*]
[*Example [2](#example-2)*: struct C {virtual void f() = 0 { }; // error}; — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4253)
[*Note [5](#note-5)*:
An abstract class type cannot be used
as a parameter or return type of
a function being defined ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) or called ([[expr.call]](expr.call "7.6.1.3Function call")),
except as specified in [[dcl.type.simple]](dcl.type.simple "9.2.9.3Simple type specifiers")[.](#3.sentence-1)
Further, an abstract class type cannot be used as
the type of an explicit type conversion ([[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10Reinterpret cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11Const cast")),
because the resulting prvalue would be of abstract class type ([[basic.lval]](basic.lval "7.2.1Value category"))[.](#3.sentence-2)
However, pointers and references to abstract class types
can appear in such contexts[.](#3.sentence-3)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4267)
A class is abstract if it has at least one pure virtual
function for which the final overrider is pure virtual[.](#4.sentence-1)
[*Example [3](#example-3)*: class ab_circle : public shape {int radius;public:void rotate(int) { }// ab_circle::draw() is a pure virtual};
Since shape::draw() is a pure virtual functionab_circle::draw() is a pure virtual by default[.](#4.sentence-2)
The alternative
declaration,class circle : public shape {int radius;public:void rotate(int) { }void draw(); // a definition is required somewhere}; would make class circle non-abstract and a definition ofcircle::draw() must be provided[.](#4.sentence-3)
— *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4296)
[*Note [6](#note-6)*:
An abstract class can be derived from a class that is not abstract, and
a pure virtual function can override a virtual function which is not
pure[.](#5.sentence-1)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4303)
Member functions can be called from a constructor (or destructor) of an
abstract class;the effect of making a virtual call ([[class.virtual]](class.virtual "11.7.3Virtual functions")) to a pure
virtual function directly or indirectly for the object being created (or
destroyed) from such a constructor (or destructor) is undefined[.](#6.sentence-1)

673
cppdraft/class/access.md Normal file
View File

@@ -0,0 +1,673 @@
[class.access]
# 11 Classes [[class]](./#class)
## 11.8 Member access control [class.access]
### [11.8.1](#general) General [[class.access.general]](class.access.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4323)
A member of a class can be
- [(1.1)](#general-1.1)
private,
that is, it can be named only by members and friends
of the class in which it is declared;
- [(1.2)](#general-1.2)
protected,
that is, it can be named only by members and friends
of the class in which it is declared, by classes derived from that class, and by their
friends (see [[class.protected]](#class.protected "11.8.5Protected member access")); or
- [(1.3)](#general-1.3)
public,
that is, it can be named anywhere without access restriction[.](#general-1.sentence-1)
[*Note [1](#general-note-1)*:
A constructor or destructor can be named by an expression ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
even though it has no name[.](#general-1.sentence-2)
— *end note*]
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4347)
A member of a class can also access all the members to which the class has access[.](#general-2.sentence-1)
A local class of a member function may access
the same members that the member function itself may access[.](#general-2.sentence-2)[96](#footnote-96 "Access permissions are thus transitive and cumulative to nested and local classes.")
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4357)
Members of a class defined with the keywordclass are private by default[.](#general-3.sentence-1)
Members of a class defined with the keywordsstruct or union are public by default[.](#general-3.sentence-2)
[*Example [1](#general-example-1)*: class X {int a; // X::a is private by default};
struct S {int a; // S::a is public by default}; — *end example*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4379)
Access control is applied uniformly to declarations and expressions[.](#general-4.sentence-1)
[*Note [2](#general-note-2)*:
Access control applies to members nominated by
friend declarations ([[class.friend]](#class.friend "11.8.4Friends")) and[*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")*s* ([[namespace.udecl]](namespace.udecl "9.10The using declaration"))[.](#general-4.sentence-2)
— *end note*]
When a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") is named,
access control is applied to it, not to the declarations that replace it[.](#general-4.sentence-3)
For an overload set, access control is applied only to
the function selected by overload resolution[.](#general-4.sentence-4)
[*Example [2](#general-example-2)*: struct S {void f(int);private:void f(double);};
void g(S* sp) { sp->f(2); // OK, access control applied after overload resolution} — *end example*]
[*Note [3](#general-note-3)*:
Because access control applies to the declarations named,
if access control is applied to a type alias,
only the accessibility of the typedef or alias declaration itself is considered[.](#general-4.sentence-5)
The accessibility of the underlying entity is not considered[.](#general-4.sentence-6)
[*Example [3](#general-example-3)*: class A {class B { };public:typedef B BB;};
void f() { A::BB x; // OK, typedef A::BB is public A::B y; // access error, A::B is private} — *end example*]
— *end note*]
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4424)
[*Note [4](#general-note-4)*:
Access control does not prevent members from being found by name lookup or
implicit conversions to base classes from being considered[.](#general-5.sentence-1)
— *end note*]
The interpretation of a given construct is
established without regard to access control[.](#general-5.sentence-2)
If the interpretation
established makes use of inaccessible members or base classes,
the construct is ill-formed[.](#general-5.sentence-3)
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4435)
All access controls in [class.access] affect the ability to name a class member
from the declaration of a particular
entity, including parts of the declaration preceding the name of the entity
being declared and, if the entity is a class, the definitions of members of
the class appearing outside the class's [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]")[.](#general-6.sentence-1)
[*Note [5](#general-note-5)*:
This access also applies to implicit references to constructors,
conversion functions, and destructors[.](#general-6.sentence-2)
— *end note*]
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4446)
[*Example [4](#general-example-4)*: class A {typedef int I; // private member I f() pre(A::x > 0); friend I g(I) post(A::x <= 0); static I x; template<int> struct Q; template<int> friend struct R;protected:struct B { };};
A::I A::f() pre(A::x > 0) { return 0; } A::I g(A::I p = A::x) post(A::x <= 0);
A::I g(A::I p) { return 0; } A::I A::x = 0;template<A::I> struct A::Q { };template<A::I> struct R { };
struct D: A::B, A { };
Here, all the uses ofA::I are well-formed becauseA::f,A::x, and A::Q are members of classA andg and R are friends of classA[.](#general-7.sentence-1)
This implies, for example, that access checking on the first use ofA::I must be deferred until it is determined that this use ofA::I is as the return type of a member of classA[.](#general-7.sentence-2)
Similarly, the use of A::B as a[*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]") is well-formed because D is derived from A, so checking of [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]")*s* must be deferred until the entire [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]") has been seen[.](#general-7.sentence-3)
— *end example*]
[8](#general-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4493)
Access is checked for a default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))
at the point of declaration,
rather than at any points of use of the default argument[.](#general-8.sentence-1)
Access checking for default arguments in function templates and in
member functions of class templates is performed as described in [[temp.inst]](temp.inst "13.9.2Implicit instantiation")[.](#general-8.sentence-2)
[9](#general-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4502)
Access for a default [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") ([[temp.param]](temp.param "13.2Template parameters"))
is checked in the context in which it appears rather than at any
points of use of it[.](#general-9.sentence-1)
[*Example [5](#general-example-5)*: class B { };template <class T> class C {protected:typedef T TT;};
template <class U, class V = typename U::TT>class D : public U { };
D <C<B> >* d; // access error, C::TT is protected — *end example*]
[96)](#footnote-96)[96)](#footnoteref-96)
Access
permissions are thus transitive and cumulative to nested
and local classes[.](#footnote-96.sentence-1)
### [11.8.2](#spec) Access specifiers [[class.access.spec]](class.access.spec)
[1](#spec-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4524)
Member declarations can be labeled by an[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") ([[class.derived]](class.derived "11.7Derived classes")):
[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") : [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]")opt
An[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") specifies the access rules for members following it
until the end of the class or until another[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") is encountered[.](#spec-1.sentence-2)
[*Example [1](#spec-example-1)*: class X {int a; // X::a is private by default: class usedpublic:int b; // X::b is publicint c; // X::c is public}; — *end example*]
[2](#spec-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4549)
Any number of access specifiers is allowed and no particular order is required[.](#spec-2.sentence-1)
[*Example [2](#spec-example-2)*: struct S {int a; // S::a is public by default: struct usedprotected:int b; // S::b is protectedprivate:int c; // S::c is privatepublic:int d; // S::d is public}; — *end example*]
[3](#spec-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4565)
When a member is redeclared within its class definition,
the access specified at its redeclaration shall
be the same as at its initial declaration[.](#spec-3.sentence-1)
[*Example [3](#spec-example-3)*: struct S {class A; enum E : int;private:class A { }; // error: cannot change accessenum E: int { e0 }; // error: cannot change access}; — *end example*]
[4](#spec-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4581)
[*Note [1](#spec-note-1)*:
In a derived class, the lookup of a base class name will find the
injected-class-name instead of the name of the base class in the scope
in which it was declared[.](#spec-4.sentence-1)
The injected-class-name might be less accessible
than the name of the base class in the scope in which it was declared[.](#spec-4.sentence-2)
— *end note*]
[*Example [4](#spec-example-4)*: class A { };class B : private A { };class C : public B { A* p; // error: injected-class-name A is inaccessible::A* q; // OK}; — *end example*]
### [11.8.3](#base) Accessibility of base classes and base class members [[class.access.base]](class.access.base)
[1](#base-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4607)
If a class is declared to be a base class ([[class.derived]](class.derived "11.7Derived classes")) for another class using thepublic access specifier, the
public members of the base class are accessible as
public members of the derived class and
protected members of the base class are accessible as
protected members of the derived class[.](#base-1.sentence-1)
If a class is declared to be a base class for another class using theprotected access specifier, the
public and protected members of the base class are accessible as
protected members of the derived class[.](#base-1.sentence-2)
If a class is declared to be a base class for another class using theprivate access specifier, the
public and protected
members of the base class are accessible as private
members of the derived class[.](#base-1.sentence-3)[97](#footnote-97 "As specified previously in [class.access], private members of a base class remain inaccessible even to derived classes unless friend declarations within the base class definition are used to grant access explicitly.")
[2](#base-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4633)
In the absence of an[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") for a base class,public is assumed when the derived class is
defined with the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]")struct andprivate is assumed when the class is
defined with the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]")class[.](#base-2.sentence-1)
[*Example [1](#base-example-1)*: class B { /* ... */ };class D1 : private B { /* ... */ };class D2 : public B { /* ... */ };class D3 : B { /* ... */ }; // B private by defaultstruct D4 : public B { /* ... */ };struct D5 : private B { /* ... */ };struct D6 : B { /* ... */ }; // B public by defaultclass D7 : protected B { /* ... */ };struct D8 : protected B { /* ... */ };
HereB is a public base ofD2,D4,
andD6,
a private base ofD1,D3,
andD5,
and a protected base ofD7 andD8[.](#base-2.sentence-2)
— *end example*]
[3](#base-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4677)
[*Note [1](#base-note-1)*:
A member of a private base class can be inaccessible as inherited,
but accessible directly[.](#base-3.sentence-1)
Because of the rules on pointer conversions ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")) and
explicit casts ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)")),
a conversion from a pointer to a derived class to a pointer
to an inaccessible base class can be ill-formed if an implicit conversion
is used, but well-formed if an explicit cast is used[.](#base-3.sentence-2)
[*Example [2](#base-example-2)*: class B {public:int mi; // non-static memberstatic int si; // static member};class D : private B {};class DD : public D {void f();};
void DD::f() { mi = 3; // error: mi is private in D si = 3; // error: si is private in D::B b;
b.mi = 3; // OK (b.mi is different from this->mi) b.si = 3; // OK (b.si is different from this->si)::B::si = 3; // OK::B* bp1 = this; // error: B is a private base class::B* bp2 = (::B*)this; // OK with cast bp2->mi = 3; // OK, access through a pointer to B.} — *end example*]
— *end note*]
[4](#base-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4714)
A base classB ofN is[*accessible*](#def:accessible "11.8.3Accessibility of base classes and base class members[class.access.base]") at*R*,
if
- [(4.1)](#base-4.1)
an invented public member ofB would be a public member ofN, or
- [(4.2)](#base-4.2)
*R* occurs in a direct member or friend of classN,
and an invented public member ofB would be a private or protected member ofN, or
- [(4.3)](#base-4.3)
*R* occurs in a direct member or friend of a classP derived fromN,
and an invented public member ofB would be a private or protected member ofP, or
- [(4.4)](#base-4.4)
there exists a classS such thatB is a base class ofS accessible at*R* andS is a base class ofN accessible at*R*[.](#base-4.sentence-1)
[*Example [3](#base-example-3)*: class B {public:int m;};
class S: private B {friend class N;};
class N: private S {void f() { B* p = this; // OK because class S satisfies the fourth condition above: B is a base class of N// accessible in f() because B is an accessible base class of S and S is an accessible// base class of N.}}; — *end example*]
[5](#base-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4786)
If a base class is accessible, one can implicitly convert a pointer to
a derived class to a pointer to that base class ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions"), [[conv.mem]](conv.mem "7.3.13Pointer-to-member conversions"))[.](#base-5.sentence-1)
[*Note [2](#base-note-2)*:
It follows that
members and friends of a classX can implicitly convert anX* to a pointer to a private or protected immediate base class ofX[.](#base-5.sentence-2)
— *end note*]
An expression E that designates a member m has a [*designating class*](#def:class,designating "11.8.3Accessibility of base classes and base class members[class.access.base]") that affects the access to m[.](#base-5.sentence-3)
This designating class is either
- [(5.1)](#base-5.1)
the innermost class of which m is directly a member
if E is a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") or
- [(5.2)](#base-5.2)
the class in whose scope name lookup performed a search
that found m otherwise[.](#base-5.sentence-4)
[*Note [3](#base-note-3)*:
This class can be explicit, e.g., when a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") is used, or implicit, e.g., when a class member access operator ([[expr.ref]](expr.ref "7.6.1.5Class member access")) is used (including cases where an implicit
“this->”
is
added)[.](#base-5.sentence-5)
If both a class member access operator and a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") are used to name the member (as inp->T::m),
the class designating the member is the class designated by the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") of the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") (that is,T)[.](#base-5.sentence-6)
— *end note*]
A memberm is accessible at the point*R* when designated in classN if
- [(5.3)](#base-5.3)
m is designated by a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]"), or
- [(5.4)](#base-5.4)
m as a member ofN is public, or
- [(5.5)](#base-5.5)
m as a member ofN is private, and*R* occurs in a direct member or friend of classN,
or
- [(5.6)](#base-5.6)
m as a member ofN is protected, and*R* occurs in a direct member or friend of classN,
or in a member of a classP derived fromN,
wherem as a member ofP is public, private, or protected, or
- [(5.7)](#base-5.7)
there exists a base classB ofN that is accessible at*R*,
andm is accessible at*R* when designated in classB[.](#base-5.sentence-7)
[*Example [4](#base-example-4)*: class B;class A {private:int i; friend void f(B*);};class B : public A { };void f(B* p) { p->i = 1; // OK, B* can be implicitly converted to A*, and f has access to i in A} — *end example*]
[6](#base-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4898)
If a class member access operator, including an implicit
“this->”,
is used to access a non-static data member or non-static
member function, the reference is ill-formed if the
left operand (considered as a pointer in the
“.”
operator case) cannot be implicitly converted to a
pointer to the designating class of the right operand[.](#base-6.sentence-1)
[*Note [4](#base-note-4)*:
This requirement is in addition to the requirement that
the member be accessible as designated[.](#base-6.sentence-2)
— *end note*]
[97)](#footnote-97)[97)](#footnoteref-97)
As specified previously in [class.access],
private members of a base class remain inaccessible even to derived classes
unless friend
declarations within the base class definition are used to grant access explicitly[.](#footnote-97.sentence-1)
### [11.8.4](#class.friend) Friends [[class.friend]](class.friend)
[1](#class.friend-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4916)
A friend of a class is a function or class that is
given permission to name the private and protected members of the class[.](#class.friend-1.sentence-1)
A class specifies its friends, if any, by way of friend declarations[.](#class.friend-1.sentence-2)
Such declarations give special access rights to the friends, but they
do not make the nominated friends members of the befriending class[.](#class.friend-1.sentence-3)
[*Example [1](#class.friend-example-1)*:
The following example illustrates the differences between
members and friends:class X {int a; friend void friend_set(X*, int);public:void member_set(int);};
void friend_set(X* p, int i) { p->a = i; }void X::member_set(int i) { a = i; }void f() { X obj;
friend_set(&obj,10);
obj.member_set(10);}
— *end example*]
[2](#class.friend-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4946)
Declaring a class to be a friend implies that private and
protected members of the class granting friendship can be named in the[*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]")*s* and member declarations of the befriended
class[.](#class.friend-2.sentence-1)
[*Example [2](#class.friend-example-2)*: class A {class B { }; friend class X;};
struct X : A::B { // OK, A::B accessible to friend A::B mx; // OK, A::B accessible to member of friendclass Y { A::B my; // OK, A::B accessible to nested member of friend};}; — *end example*]
[*Example [3](#class.friend-example-3)*: class X {enum { a=100 }; friend class Y;};
class Y {int v[X::a]; // OK, Y is a friend of X};
class Z {int v[X::a]; // error: X::a is private}; — *end example*]
[3](#class.friend-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4984)
A friend declaration that does not declare a function
shall be a [*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1General[class.mem.general]")[.](#class.friend-3.sentence-1)
[*Note [1](#class.friend-note-1)*:
A friend declaration can be the[*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") in
a [*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]") ([[temp.pre]](temp.pre "13.1Preamble"), [[temp.friend]](temp.friend "13.7.5Friends"))[.](#class.friend-3.sentence-2)
— *end note*]
If a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1General[class.mem.general]") in a friend declaration
designates a (possibly
cv-qualified) class type, that class is declared as a friend; otherwise, the[*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1General[class.mem.general]") is ignored[.](#class.friend-3.sentence-3)
[*Example [4](#class.friend-example-4)*: class C;typedef C Ct;class E;
class X1 {friend C; // OK, class C is a friend};
class X2 {friend Ct; // OK, class C is a friendfriend D; // error: D not foundfriend class D; // OK, elaborated-type-specifier declares new class};
template <typename ... Ts> class R {friend Ts...;};
template <class... Ts, class... Us>class R<R<Ts...>, R<Us...>> {friend Ts::Nested..., Us...;};
R<C> rc; // class C is a friend of R<C> R<C, E> rce; // classes C and E are friends of R<C, E> R<int> Ri; // OK, “friend int;'' is ignoredstruct E { struct Nested; };
R<R<E>, R<C, int>> rr; // E::Nested and C are friends of R<R<E>, R<C, int>> — *end example*]
[4](#class.friend-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5032)
[*Note [2](#class.friend-note-2)*:
A friend declaration refers to an entity, not (all overloads of) a name[.](#class.friend-4.sentence-1)
A member function of a classX can be a friend of
a classY[.](#class.friend-4.sentence-2)
[*Example [5](#class.friend-example-5)*: class Y {friend char* X::foo(int); friend X::X(char); // constructors can be friendsfriend X::~X(); // destructors can be friends}; — *end example*]
— *end note*]
[5](#class.friend-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5053)
A function may be defined in a friend declaration of a class if and only if the
class is a non-local class ([[class.local]](class.local "11.6Local class declarations")) and the function name is unqualified[.](#class.friend-5.sentence-1)
[*Example [6](#class.friend-example-6)*: class M {friend void f() { } // definition of global f, a friend of M,// not the definition of a member function}; — *end example*]
[6](#class.friend-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5066)
Such a function is implicitly an inline ([[dcl.inline]](dcl.inline "9.2.8The inline specifier")) function
if it is attached to the global module[.](#class.friend-6.sentence-1)
[*Note [3](#class.friend-note-3)*:
If a friend function is defined outside a class,
it is not in the scope of the class[.](#class.friend-6.sentence-2)
— *end note*]
[7](#class.friend-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5074)
No[*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") shall appear in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a friend declaration[.](#class.friend-7.sentence-1)
[8](#class.friend-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5081)
A member nominated by a friend declaration shall be accessible in the
class containing the friend declaration[.](#class.friend-8.sentence-1)
The meaning of the friend declaration is the same whether the friend declaration
appears in the private, protected, or public ([[class.mem]](class.mem "11.4Class members"))
portion of the class[*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]")[.](#class.friend-8.sentence-2)
[9](#class.friend-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5090)
Friendship is neither inherited nor transitive[.](#class.friend-9.sentence-1)
[*Example [7](#class.friend-example-7)*: class A {friend class B; int a;};
class B {friend class C;};
class C {void f(A* p) { p->a++; // error: C is not a friend of A despite being a friend of a friend}};
class D : public B {void f(A* p) { p->a++; // error: D is not a friend of A despite being derived from a friend}}; — *end example*]
[10](#class.friend-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5118)
[*Note [4](#class.friend-note-4)*:
A friend declaration never binds any names ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators"), [[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers"))[.](#class.friend-10.sentence-1)
— *end note*]
[*Example [8](#class.friend-example-8)*: // Assume f and g have not yet been declared.void h(int);template <class T> void f2(T);namespace A {class X {friend void f(X); // A::f(X) is a friendclass Y {friend void g(); // A::g is a friendfriend void h(int); // A::h is a friend// ::h not consideredfriend void f2<>(int); // ::f2<>(int) is a friend}; }; // A::f, A::g and A::h are not visible here X x; void g() { f(x); } // definition of A::gvoid f(X) { /* ... */ } // definition of A::fvoid h(int) { /* ... */ } // definition of A::h// A::f, A::g and A::h are visible here and known to be friends}using A::x;
void h() { A::f(x);
A::X::f(x); // error: f is not a member of A::X A::X::Y::g(); // error: g is not a member of A::X::Y} — *end example*]
[*Example [9](#class.friend-example-9)*: class X;void a();void f() {class Y; extern void b(); class A {friend class X; // OK, but X is a local class, not ::Xfriend class Y; // OKfriend class Z; // OK, introduces local class Zfriend void a(); // error, ::a is not consideredfriend void b(); // OKfriend void c(); // error};
X* px; // OK, but ::X is found Z* pz; // error: no Z is found} — *end example*]
### [11.8.5](#class.protected) Protected member access [[class.protected]](class.protected)
[1](#class.protected-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5181)
An additional access check beyond those described earlier in [class.access]
is applied when a non-static data member or non-static member function is a
protected member of its naming class ([[class.access.base]](#base "11.8.3Accessibility of base classes and base class members"))[.](#class.protected-1.sentence-1)[98](#footnote-98 "This additional check does not apply to other members, e.g., static data members or enumerator member constants.")
As described earlier, access to a protected member is granted because the
reference occurs in a friend or direct member of some class C[.](#class.protected-1.sentence-2)
If the access is
to form a pointer to member ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators")), the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") shall denote C or a class derived fromC[.](#class.protected-1.sentence-3)
All other accesses involve a (possibly implicit) object
expression ([[expr.ref]](expr.ref "7.6.1.5Class member access"))[.](#class.protected-1.sentence-4)
In this case, the class of the object expression shall beC or a class derived from C[.](#class.protected-1.sentence-5)
[*Example [1](#class.protected-example-1)*: class B {protected:int i; static int j;};
class D1 : public B {};
class D2 : public B {friend void fr(B*,D1*,D2*); void mem(B*,D1*);};
void fr(B* pb, D1* p1, D2* p2) { pb->i = 1; // error p1->i = 2; // error p2->i = 3; // OK (access through a D2) p2->B::i = 4; // OK (access through a D2, even though naming class is B)int B::* pmi_B = &B::i; // errorint B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*) B::j = 5; // error: not a friend of naming class B D2::j = 6; // OK (because refers to static member)}void D2::mem(B* pb, D1* p1) { pb->i = 1; // error p1->i = 2; // error i = 3; // OK (access through this) B::i = 4; // OK (access through this, qualification ignored)int B::* pmi_B = &B::i; // errorint B::* pmi_B2 = &D2::i; // OK j = 5; // OK (because j refers to static member) B::j = 6; // OK (because B::j refers to static member)}void g(B* pb, D1* p1, D2* p2) { pb->i = 1; // error p1->i = 2; // error p2->i = 3; // error} — *end example*]
[98)](#footnote-98)[98)](#footnoteref-98)
This
additional check does not apply to other members,
e.g., static data members or enumerator member constants[.](#footnote-98.sentence-1)
### [11.8.6](#virt) Access to virtual functions [[class.access.virt]](class.access.virt)
[1](#virt-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5246)
The access rules ([class.access]) for a virtual function are determined by its declaration
and are not affected by the rules for a function that later overrides it[.](#virt-1.sentence-1)
[*Example [1](#virt-example-1)*: class B {public:virtual int f();};
class D : public B {private:int f();};
void f() { D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK, B::f() is public, D::f() is invoked pd->f(); // error: D::f() is private} — *end example*]
[2](#virt-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5272)
Access is checked at the call point using the type of the expression used
to denote the object for which the member function is called
(B* in the example above)[.](#virt-2.sentence-1)
The access of the member function in the class in which it was defined
(D in the example above) is in general not known[.](#virt-2.sentence-2)
### [11.8.7](#class.paths) Multiple access [[class.paths]](class.paths)
[1](#class.paths-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5284)
If a declaration can be reached by several paths through a multiple inheritance
graph, the access is that of the path that gives most access[.](#class.paths-1.sentence-1)
[*Example [1](#class.paths-example-1)*: class W { public: void f(); };class A : private virtual W { };class B : public virtual W { };class C : public A, public B {void f() { W::f(); } // OK};
SinceW::f() is available toC::f() along the public path throughB,
access is allowed[.](#class.paths-1.sentence-2)
— *end example*]
### [11.8.8](#nest) Nested classes [[class.access.nest]](class.access.nest)
[1](#nest-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5310)
A nested class is a member and as such has the same access rights as any other member[.](#nest-1.sentence-1)
The members of an enclosing class have no special access to members of a nested
class; the usual access rules ([class.access]) shall be obeyed[.](#nest-1.sentence-2)
[*Example [1](#nest-example-1)*: class E {int x; class B { }; class I { B b; // OK, E::I can access E::Bint y; void f(E* p, int i) { p->x = i; // OK, E::I can access E::x}}; int g(I* p) {return p->y; // error: I::y is private}}; — *end example*]

View File

@@ -0,0 +1,191 @@
[class.access.base]
# 11 Classes [[class]](./#class)
## 11.8 Member access control [[class.access]](class.access#base)
### 11.8.3 Accessibility of base classes and base class members [class.access.base]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4607)
If a class is declared to be a base class ([[class.derived]](class.derived "11.7Derived classes")) for another class using thepublic access specifier, the
public members of the base class are accessible as
public members of the derived class and
protected members of the base class are accessible as
protected members of the derived class[.](#1.sentence-1)
If a class is declared to be a base class for another class using theprotected access specifier, the
public and protected members of the base class are accessible as
protected members of the derived class[.](#1.sentence-2)
If a class is declared to be a base class for another class using theprivate access specifier, the
public and protected
members of the base class are accessible as private
members of the derived class[.](#1.sentence-3)[97](#footnote-97 "As specified previously in [class.access], private members of a base class remain inaccessible even to derived classes unless friend declarations within the base class definition are used to grant access explicitly.")
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4633)
In the absence of an[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") for a base class,public is assumed when the derived class is
defined with the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]")struct andprivate is assumed when the class is
defined with the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]")class[.](#2.sentence-1)
[*Example [1](#example-1)*: class B { /* ... */ };class D1 : private B { /* ... */ };class D2 : public B { /* ... */ };class D3 : B { /* ... */ }; // B private by defaultstruct D4 : public B { /* ... */ };struct D5 : private B { /* ... */ };struct D6 : B { /* ... */ }; // B public by defaultclass D7 : protected B { /* ... */ };struct D8 : protected B { /* ... */ };
HereB is a public base ofD2,D4,
andD6,
a private base ofD1,D3,
andD5,
and a protected base ofD7 andD8[.](#2.sentence-2)
— *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4677)
[*Note [1](#note-1)*:
A member of a private base class can be inaccessible as inherited,
but accessible directly[.](#3.sentence-1)
Because of the rules on pointer conversions ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions")) and
explicit casts ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)")),
a conversion from a pointer to a derived class to a pointer
to an inaccessible base class can be ill-formed if an implicit conversion
is used, but well-formed if an explicit cast is used[.](#3.sentence-2)
[*Example [2](#example-2)*: class B {public:int mi; // non-static memberstatic int si; // static member};class D : private B {};class DD : public D {void f();};
void DD::f() { mi = 3; // error: mi is private in D si = 3; // error: si is private in D::B b;
b.mi = 3; // OK (b.mi is different from this->mi) b.si = 3; // OK (b.si is different from this->si)::B::si = 3; // OK::B* bp1 = this; // error: B is a private base class::B* bp2 = (::B*)this; // OK with cast bp2->mi = 3; // OK, access through a pointer to B.} — *end example*]
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4714)
A base classB ofN is[*accessible*](#def:accessible "11.8.3Accessibility of base classes and base class members[class.access.base]") at*R*,
if
- [(4.1)](#4.1)
an invented public member ofB would be a public member ofN, or
- [(4.2)](#4.2)
*R* occurs in a direct member or friend of classN,
and an invented public member ofB would be a private or protected member ofN, or
- [(4.3)](#4.3)
*R* occurs in a direct member or friend of a classP derived fromN,
and an invented public member ofB would be a private or protected member ofP, or
- [(4.4)](#4.4)
there exists a classS such thatB is a base class ofS accessible at*R* andS is a base class ofN accessible at*R*[.](#4.sentence-1)
[*Example [3](#example-3)*: class B {public:int m;};
class S: private B {friend class N;};
class N: private S {void f() { B* p = this; // OK because class S satisfies the fourth condition above: B is a base class of N// accessible in f() because B is an accessible base class of S and S is an accessible// base class of N.}}; — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4786)
If a base class is accessible, one can implicitly convert a pointer to
a derived class to a pointer to that base class ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions"), [[conv.mem]](conv.mem "7.3.13Pointer-to-member conversions"))[.](#5.sentence-1)
[*Note [2](#note-2)*:
It follows that
members and friends of a classX can implicitly convert anX* to a pointer to a private or protected immediate base class ofX[.](#5.sentence-2)
— *end note*]
An expression E that designates a member m has a [*designating class*](#def:class,designating "11.8.3Accessibility of base classes and base class members[class.access.base]") that affects the access to m[.](#5.sentence-3)
This designating class is either
- [(5.1)](#5.1)
the innermost class of which m is directly a member
if E is a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]") or
- [(5.2)](#5.2)
the class in whose scope name lookup performed a search
that found m otherwise[.](#5.sentence-4)
[*Note [3](#note-3)*:
This class can be explicit, e.g., when a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") is used, or implicit, e.g., when a class member access operator ([[expr.ref]](expr.ref "7.6.1.5Class member access")) is used (including cases where an implicit
“this->”
is
added)[.](#5.sentence-5)
If both a class member access operator and a[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") are used to name the member (as inp->T::m),
the class designating the member is the class designated by the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") of the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") (that is,T)[.](#5.sentence-6)
— *end note*]
A memberm is accessible at the point*R* when designated in classN if
- [(5.3)](#5.3)
m is designated by a [*splice-expression*](expr.prim.splice#nt:splice-expression "7.5.9Expression splicing[expr.prim.splice]"), or
- [(5.4)](#5.4)
m as a member ofN is public, or
- [(5.5)](#5.5)
m as a member ofN is private, and*R* occurs in a direct member or friend of classN,
or
- [(5.6)](#5.6)
m as a member ofN is protected, and*R* occurs in a direct member or friend of classN,
or in a member of a classP derived fromN,
wherem as a member ofP is public, private, or protected, or
- [(5.7)](#5.7)
there exists a base classB ofN that is accessible at*R*,
andm is accessible at*R* when designated in classB[.](#5.sentence-7)
[*Example [4](#example-4)*: class B;class A {private:int i; friend void f(B*);};class B : public A { };void f(B* p) { p->i = 1; // OK, B* can be implicitly converted to A*, and f has access to i in A} — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4898)
If a class member access operator, including an implicit
“this->”,
is used to access a non-static data member or non-static
member function, the reference is ill-formed if the
left operand (considered as a pointer in the
“.”
operator case) cannot be implicitly converted to a
pointer to the designating class of the right operand[.](#6.sentence-1)
[*Note [4](#note-4)*:
This requirement is in addition to the requirement that
the member be accessible as designated[.](#6.sentence-2)
— *end note*]
[97)](#footnote-97)[97)](#footnoteref-97)
As specified previously in [[class.access]](class.access "11.8Member access control"),
private members of a base class remain inaccessible even to derived classes
unless friend
declarations within the base class definition are used to grant access explicitly[.](#footnote-97.sentence-1)

View File

@@ -0,0 +1,181 @@
[class.access.general]
# 11 Classes [[class]](./#class)
## 11.8 Member access control [[class.access]](class.access#general)
### 11.8.1 General [class.access.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4323)
A member of a class can be
- [(1.1)](#1.1)
private,
that is, it can be named only by members and friends
of the class in which it is declared;
- [(1.2)](#1.2)
protected,
that is, it can be named only by members and friends
of the class in which it is declared, by classes derived from that class, and by their
friends (see [[class.protected]](class.protected "11.8.5Protected member access")); or
- [(1.3)](#1.3)
public,
that is, it can be named anywhere without access restriction[.](#1.sentence-1)
[*Note [1](#note-1)*:
A constructor or destructor can be named by an expression ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
even though it has no name[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4347)
A member of a class can also access all the members to which the class has access[.](#2.sentence-1)
A local class of a member function may access
the same members that the member function itself may access[.](#2.sentence-2)[96](#footnote-96 "Access permissions are thus transitive and cumulative to nested and local classes.")
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4357)
Members of a class defined with the keywordclass are private by default[.](#3.sentence-1)
Members of a class defined with the keywordsstruct or union are public by default[.](#3.sentence-2)
[*Example [1](#example-1)*: class X {int a; // X::a is private by default};
struct S {int a; // S::a is public by default}; — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4379)
Access control is applied uniformly to declarations and expressions[.](#4.sentence-1)
[*Note [2](#note-2)*:
Access control applies to members nominated by
friend declarations ([[class.friend]](class.friend "11.8.4Friends")) and[*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")*s* ([[namespace.udecl]](namespace.udecl "9.10The using declaration"))[.](#4.sentence-2)
— *end note*]
When a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") is named,
access control is applied to it, not to the declarations that replace it[.](#4.sentence-3)
For an overload set, access control is applied only to
the function selected by overload resolution[.](#4.sentence-4)
[*Example [2](#example-2)*: struct S {void f(int);private:void f(double);};
void g(S* sp) { sp->f(2); // OK, access control applied after overload resolution} — *end example*]
[*Note [3](#note-3)*:
Because access control applies to the declarations named,
if access control is applied to a type alias,
only the accessibility of the typedef or alias declaration itself is considered[.](#4.sentence-5)
The accessibility of the underlying entity is not considered[.](#4.sentence-6)
[*Example [3](#example-3)*: class A {class B { };public:typedef B BB;};
void f() { A::BB x; // OK, typedef A::BB is public A::B y; // access error, A::B is private} — *end example*]
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4424)
[*Note [4](#note-4)*:
Access control does not prevent members from being found by name lookup or
implicit conversions to base classes from being considered[.](#5.sentence-1)
— *end note*]
The interpretation of a given construct is
established without regard to access control[.](#5.sentence-2)
If the interpretation
established makes use of inaccessible members or base classes,
the construct is ill-formed[.](#5.sentence-3)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4435)
All access controls in [[class.access]](class.access "11.8Member access control") affect the ability to name a class member
from the declaration of a particular
entity, including parts of the declaration preceding the name of the entity
being declared and, if the entity is a class, the definitions of members of
the class appearing outside the class's [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]")[.](#6.sentence-1)
[*Note [5](#note-5)*:
This access also applies to implicit references to constructors,
conversion functions, and destructors[.](#6.sentence-2)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4446)
[*Example [4](#example-4)*: class A {typedef int I; // private member I f() pre(A::x > 0); friend I g(I) post(A::x <= 0); static I x; template<int> struct Q; template<int> friend struct R;protected:struct B { };};
A::I A::f() pre(A::x > 0) { return 0; } A::I g(A::I p = A::x) post(A::x <= 0);
A::I g(A::I p) { return 0; } A::I A::x = 0;template<A::I> struct A::Q { };template<A::I> struct R { };
struct D: A::B, A { };
Here, all the uses ofA::I are well-formed becauseA::f,A::x, and A::Q are members of classA andg and R are friends of classA[.](#7.sentence-1)
This implies, for example, that access checking on the first use ofA::I must be deferred until it is determined that this use ofA::I is as the return type of a member of classA[.](#7.sentence-2)
Similarly, the use of A::B as a[*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]") is well-formed because D is derived from A, so checking of [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]")*s* must be deferred until the entire [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]") has been seen[.](#7.sentence-3)
— *end example*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4493)
Access is checked for a default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))
at the point of declaration,
rather than at any points of use of the default argument[.](#8.sentence-1)
Access checking for default arguments in function templates and in
member functions of class templates is performed as described in [[temp.inst]](temp.inst "13.9.2Implicit instantiation")[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4502)
Access for a default [*template-argument*](temp.names#nt:template-argument "13.3Names of template specializations[temp.names]") ([[temp.param]](temp.param "13.2Template parameters"))
is checked in the context in which it appears rather than at any
points of use of it[.](#9.sentence-1)
[*Example [5](#example-5)*: class B { };template <class T> class C {protected:typedef T TT;};
template <class U, class V = typename U::TT>class D : public U { };
D <C<B> >* d; // access error, C::TT is protected — *end example*]
[96)](#footnote-96)[96)](#footnoteref-96)
Access
permissions are thus transitive and cumulative to nested
and local classes[.](#footnote-96.sentence-1)

View File

@@ -0,0 +1,18 @@
[class.access.nest]
# 11 Classes [[class]](./#class)
## 11.8 Member access control [[class.access]](class.access#nest)
### 11.8.8 Nested classes [class.access.nest]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5310)
A nested class is a member and as such has the same access rights as any other member[.](#1.sentence-1)
The members of an enclosing class have no special access to members of a nested
class; the usual access rules ([[class.access]](class.access "11.8Member access control")) shall be obeyed[.](#1.sentence-2)
[*Example [1](#example-1)*: class E {int x; class B { }; class I { B b; // OK, E::I can access E::Bint y; void f(E* p, int i) { p->x = i; // OK, E::I can access E::x}}; int g(I* p) {return p->y; // error: I::y is private}}; — *end example*]

View File

@@ -0,0 +1,55 @@
[class.access.spec]
# 11 Classes [[class]](./#class)
## 11.8 Member access control [[class.access]](class.access#spec)
### 11.8.2 Access specifiers [class.access.spec]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4524)
Member declarations can be labeled by an[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") ([[class.derived]](class.derived "11.7Derived classes")):
[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") : [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]")opt
An[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") specifies the access rules for members following it
until the end of the class or until another[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") is encountered[.](#1.sentence-2)
[*Example [1](#example-1)*: class X {int a; // X::a is private by default: class usedpublic:int b; // X::b is publicint c; // X::c is public}; — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4549)
Any number of access specifiers is allowed and no particular order is required[.](#2.sentence-1)
[*Example [2](#example-2)*: struct S {int a; // S::a is public by default: struct usedprotected:int b; // S::b is protectedprivate:int c; // S::c is privatepublic:int d; // S::d is public}; — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4565)
When a member is redeclared within its class definition,
the access specified at its redeclaration shall
be the same as at its initial declaration[.](#3.sentence-1)
[*Example [3](#example-3)*: struct S {class A; enum E : int;private:class A { }; // error: cannot change accessenum E: int { e0 }; // error: cannot change access}; — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4581)
[*Note [1](#note-1)*:
In a derived class, the lookup of a base class name will find the
injected-class-name instead of the name of the base class in the scope
in which it was declared[.](#4.sentence-1)
The injected-class-name might be less accessible
than the name of the base class in the scope in which it was declared[.](#4.sentence-2)
— *end note*]
[*Example [4](#example-4)*: class A { };class B : private A { };class C : public B { A* p; // error: injected-class-name A is inaccessible::A* q; // OK}; — *end example*]

View File

@@ -0,0 +1,35 @@
[class.access.virt]
# 11 Classes [[class]](./#class)
## 11.8 Member access control [[class.access]](class.access#virt)
### 11.8.6 Access to virtual functions [class.access.virt]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5246)
The access rules ([[class.access]](class.access "11.8Member access control")) for a virtual function are determined by its declaration
and are not affected by the rules for a function that later overrides it[.](#1.sentence-1)
[*Example [1](#example-1)*: class B {public:virtual int f();};
class D : public B {private:int f();};
void f() { D d;
B* pb = &d;
D* pd = &d;
pb->f(); // OK, B::f() is public, D::f() is invoked pd->f(); // error: D::f() is private} — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5272)
Access is checked at the call point using the type of the expression used
to denote the object for which the member function is called
(B* in the example above)[.](#2.sentence-1)
The access of the member function in the class in which it was defined
(D in the example above) is in general not known[.](#2.sentence-2)

378
cppdraft/class/base/init.md Normal file
View File

@@ -0,0 +1,378 @@
[class.base.init]
# 11 Classes [[class]](./#class)
## 11.9 Initialization [[class.init]](class.init#class.base.init)
### 11.9.3 Initializing bases and members [class.base.init]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5485)
In the definition of a constructor for a class,
initializers for direct and virtual base class subobjects and
non-static data members can be specified by a[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]"),
which has the form
[ctor-initializer:](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]")
: [*mem-initializer-list*](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]")
[mem-initializer-list:](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]")
[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") ...opt
[*mem-initializer-list*](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]") , [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") ...opt
[mem-initializer:](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")
[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
[mem-initializer-id:](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]")
[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5514)
Lookup for an unqualified name in a [*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") ignores the constructor's function parameter scope[.](#2.sentence-1)
[*Note [1](#note-1)*:
If the constructor's class contains a member with the same name as a direct
or virtual base class of the class, a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") naming the member or base class and composed of a single identifier
refers to the class member[.](#2.sentence-2)
A[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") for the hidden base class can be specified using a qualified name[.](#2.sentence-3)
— *end note*]
Unless the[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") names the constructor's class,
a non-static data member of the constructor's class, or
a direct or virtual base of that class,
the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is ill-formed[.](#2.sentence-4)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5536)
A[*mem-initializer-list*](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]") can initialize a base class using any [*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1General[class.derived.general]") that denotes that base class type[.](#3.sentence-1)
[*Example [1](#example-1)*: struct A { A(); };typedef A global_A;struct B { };struct C: public A, public B { C(); };
C::C(): global_A() { } // mem-initializer for base A — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5550)
If a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") is ambiguous because it designates both a direct non-virtual base class and
an indirect virtual base class, the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is ill-formed[.](#4.sentence-1)
[*Example [2](#example-2)*: struct A { A(); };struct B: public virtual A { };struct C: public A, public B { C(); };
C::C(): A() { } // error: which A? — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5566)
A[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") may initialize a variant member of the
constructor's class[.](#5.sentence-1)
If a[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") specifies more than one[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") for the same member or for the same base class,
the[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") is ill-formed[.](#5.sentence-2)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5580)
A [*mem-initializer-list*](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]") can delegate to another
constructor of the constructor's class using any[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1General[class.derived.general]") that denotes the constructor's class itself[.](#6.sentence-1)
If a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") designates the constructor's class,
it shall be the only [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]"); the constructor
is a [*delegating constructor*](#def:constructor,delegating "11.9.3Initializing bases and members[class.base.init]"), and the constructor selected by the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is the [*target constructor*](#def:constructor,target "11.9.3Initializing bases and members[class.base.init]")[.](#6.sentence-2)
The target constructor is selected by overload resolution[.](#6.sentence-3)
Once the target constructor returns, the body of the delegating constructor
is executed[.](#6.sentence-4)
If a constructor delegates to itself directly or indirectly,
the program is ill-formed, no diagnostic required[.](#6.sentence-5)
[*Example [3](#example-3)*: struct C { C( int ) { } // #1: non-delegating constructor C(): C(42) { } // #2: delegates to #1 C( char c ) : C(42.0) { } // #3: ill-formed due to recursion with #4 C( double d ) : C('a') { } // #4: ill-formed due to recursion with #3}; — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5603)
The[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") in a[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is used to initialize the
designated subobject (or, in the case of a delegating constructor, the complete class object)
according to the initialization rules of [[dcl.init]](dcl.init "9.5Initializers") for direct-initialization[.](#7.sentence-1)
[*Example [4](#example-4)*: struct B1 { B1(int); /* ... */ };struct B2 { B2(int); /* ... */ };struct D : B1, B2 { D(int);
B1 b; const int c;};
D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4) { /* ... */ } D d(10); — *end example*]
[*Note [2](#note-2)*:
The initialization
performed by each [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") constitutes a full-expression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))[.](#7.sentence-2)
Any expression in
a[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is evaluated as part of the full-expression that performs the initialization[.](#7.sentence-3)
— *end note*]
A [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") where the [*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") denotes
a virtual base class is ignored during execution of a constructor of any class that is
not the most derived class[.](#7.sentence-4)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5641)
A temporary expression bound to a reference member in a [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is ill-formed[.](#8.sentence-1)
[*Example [5](#example-5)*: struct A { A() : v(42) { } // errorconst int& v;}; — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5653)
In a non-delegating constructor
other than an implicitly-defined copy/move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")),
if a given potentially constructed subobject is not designated by a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") (including the case where there is no[*mem-initializer-list*](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]") because the constructor has no[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]")),
then
- [(9.1)](#9.1)
if the entity is a non-static data member that has
a default member initializer ([[class.mem]](class.mem "11.4Class members")) and either
* [(9.1.1)](#9.1.1)
the constructor's class is a union ([[class.union]](class.union "11.5Unions")), and no other variant
member of that union is designated by a [*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") or
* [(9.1.2)](#9.1.2)
the constructor's class is not a union, and, if the entity is a member of an
anonymous union, no other member of that union is designated by a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]"),
the entity is initialized from its default member initializer
as specified in [[dcl.init]](dcl.init "9.5Initializers");
- [(9.2)](#9.2)
otherwise, if the entity is an anonymous union or a variant member ([[class.union.anon]](class.union.anon "11.5.2Anonymous unions")), no initialization is performed;
- [(9.3)](#9.3)
otherwise, the entity is default-initialized ([[dcl.init]](dcl.init "9.5Initializers"))[.](#9.sentence-1)
[*Note [3](#note-3)*:
An abstract class ([[class.abstract]](class.abstract "11.7.4Abstract classes")) is never a most derived
class, thus its constructors never initialize virtual base classes, therefore the
corresponding [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")*s* can be omitted[.](#9.sentence-2)
— *end note*]
An attempt to initialize more than one non-static data member of a union renders the
program ill-formed[.](#9.sentence-3)
[*Note [4](#note-4)*:
After the call to a constructor for classX for an object with automatic or dynamic storage duration
has completed, if
the constructor was not invoked as part of value-initialization and
a member ofX is neither initialized nor
given a value
during execution of the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of the body of the constructor,
the member has an indeterminate or erroneous value ([[basic.indet]](basic.indet "6.8.5Indeterminate and erroneous values"))[.](#9.sentence-4)
— *end note*]
[*Example [6](#example-6)*: struct A { A();};
struct B { B(int);};
struct C { C() { } // initializes members as follows: A a; // OK, calls A::A()const B b; // error: B has no default constructorint i; // OK, i has indeterminate or erroneous valueint j = 5; // OK, j has the value 5}; — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5724)
If a given non-static data member has both a default member initializer
and a [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]"), the initialization specified by the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is performed, and the non-static data member's
default member initializer is ignored[.](#10.sentence-1)
[*Example [7](#example-7)*:
Givenstruct A {int i = /* some integer expression with side effects */ ;
A(int arg) : i(arg) { }// ...}; the A(int) constructor will simply initialize i to the value ofarg, and theside effects in i's default member initializer
will not take place[.](#10.sentence-2)
— *end example*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5748)
A temporary expression bound to a reference member from a
default member initializer is ill-formed[.](#11.sentence-1)
[*Example [8](#example-8)*: struct A { A() = default; // OK A(int v) : v(v) { } // OKconst int& v = 42; // OK};
A a1; // error: ill-formed binding of temporary to reference A a2(1); // OK, unfortunately — *end example*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5763)
In a non-delegating constructor, the destructor for each potentially constructed
subobject of class type is potentially invoked ([[class.dtor]](class.dtor "11.4.7Destructors"))[.](#12.sentence-1)
[*Note [5](#note-5)*:
This provision ensures that destructors can be called for fully-constructed
subobjects in case an exception is thrown ([[except.ctor]](except.ctor "14.3Stack unwinding"))[.](#12.sentence-2)
— *end note*]
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5771)
In a non-delegating constructor, initialization
proceeds in the following order:
- [(13.1)](#13.1)
First, and only for the constructor of the most derived class ([[intro.object]](intro.object "6.8.2Object model")),
virtual base classes are initialized in the order they appear on a
depth-first left-to-right traversal of the directed acyclic graph of
base classes,
where “left-to-right” is the order of appearance of the base classes
in the derived class[*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]")[.](#13.1.sentence-1)
- [(13.2)](#13.2)
Then, direct base classes are initialized in declaration order
as they appear in the[*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]") (regardless of the order of the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")*s*)[.](#13.2.sentence-1)
- [(13.3)](#13.3)
Then, non-static data members are initialized in the order
they were declared in the class definition
(again regardless of the order of the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")*s*)[.](#13.3.sentence-1)
- [(13.4)](#13.4)
Finally, the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of the constructor
body is executed[.](#13.4.sentence-1)
[*Note [6](#note-6)*:
The declaration order is mandated to ensure that base and member
subobjects are destroyed in the reverse order of initialization[.](#13.sentence-2)
— *end note*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5807)
[*Example [9](#example-9)*: struct V { V();
V(int);};
struct A : virtual V { A();
A(int);};
struct B : virtual V { B();
B(int);};
struct C : A, B, virtual V { C();
C(int);};
A::A(int i) : V(i) { /* ... */ } B::B(int i) { /* ... */ } C::C(int i) { /* ... */ } V v(1); // use V(int) A a(2); // use V(int) B b(3); // use V() C c(4); // use V() — *end example*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5841)
[*Note [7](#note-7)*:
The [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") of a [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is in the function parameter scope of the constructor
and can use this to refer to the object being initialized[.](#15.sentence-1)
— *end note*]
[*Example [10](#example-10)*: class X {int a; int b; int i; int j;public:const int& r;
X(int i): r(a), b(i), i(i), j(this->i) { }};
initializesX::r to refer toX::a,
initializesX::b with the value of the constructor parameteri,
initializesX::i with the value of the constructor parameteri,
and initializesX::j with the value ofX::i;
this takes place each time an object of classX is created[.](#15.sentence-2)
— *end example*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5883)
Member functions (including virtual member functions, [[class.virtual]](class.virtual "11.7.3Virtual functions")) can be
called for an object under construction or destruction[.](#16.sentence-1)
Similarly, an object under construction or destruction can be the operand of thetypeid operator ([[expr.typeid]](expr.typeid "7.6.1.8Type identification")) or of adynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7Dynamic cast"))[.](#16.sentence-2)
However, if these operations are performed
during evaluation of
- [(16.1)](#16.1)
a [*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") (or in a function called directly or indirectly from a[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]"))
before all the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")*s* for base classes have completed,
- [(16.2)](#16.2)
a precondition assertion of a constructor, or
- [(16.3)](#16.3)
a postcondition assertion of a destructor ([[dcl.contract.func]](dcl.contract.func "9.4.1General")),
the program has undefined behavior[.](#16.sentence-3)
[*Example [11](#example-11)*: class A {public: A(int);};
class B : public A {int j;public:int f();
B() : A(f()), // undefined behavior: calls member function but base A not yet initialized j(f()) { } // well-defined: bases are all initialized};
class C {public: C(int);};
class D : public B, C {int i;public: D() : C(f()), // undefined behavior: calls member function but base C not yet initialized i(f()) { } // well-defined: bases are all initialized}; — *end example*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5936)
[*Note [8](#note-8)*:
[[class.cdtor]](class.cdtor "11.9.5Construction and destruction") describes the results of virtual function calls,typeid anddynamic_casts
during construction for the well-defined cases;
that is, describes the polymorphic behavior
of an object under construction[.](#17.sentence-1)
— *end note*]
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5947)
A [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") followed by an ellipsis is
a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")) that initializes the base
classes specified by a pack expansion in the [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]") for the class[.](#18.sentence-1)
[*Example [12](#example-12)*: template<class... Mixins>class X : public Mixins... {public: X(const Mixins&... mixins) : Mixins(mixins)... { }}; — *end example*]

116
cppdraft/class/bit.md Normal file
View File

@@ -0,0 +1,116 @@
[class.bit]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.bit)
### 11.4.10 Bit-fields [class.bit]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2871)
A [*member-declarator*](class.mem.general#nt:member-declarator "11.4.1General[class.mem.general]") of the form
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt : [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")opt
specifies a bit-field[.](#1.sentence-1)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains
to the entity being declared[.](#1.sentence-2)
A bit-field shall not be a static member[.](#1.sentence-3)
A bit-field shall have integral or (possibly cv-qualified) enumeration type;
the bit-field semantic property is not part of the type of the class member[.](#1.sentence-4)
The [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") shall be an integral constant expression
with a value greater than or equal to zero and
is called the [*width*](simd.general#def:width "29.10.1General[simd.general]") of the bit-field[.](#1.sentence-5)
If the width of a bit-field is larger than
the width of the bit-field's type
(or, in case of an enumeration type, of its underlying type),
the extra bits are padding bits ([[basic.types.general]](basic.types.general#term.padding.bits "6.9.1General"))[.](#1.sentence-6)
Allocation of bit-fields within a class object isimplementation-defined[.](#1.sentence-7)
Alignment of bit-fields is implementation-defined[.](#1.sentence-8)
Bit-fields are packed into some addressable allocation unit[.](#1.sentence-9)
[*Note [1](#note-1)*:
Bit-fields straddle allocation units on some machines and not on others[.](#1.sentence-10)
Bit-fields are assigned right-to-left on some machines, left-to-right on
others[.](#1.sentence-11)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2905)
A declaration for a bit-field that omits the [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") declares an [*unnamed bit-field*](#def:bit-field,unnamed "11.4.10Bit-fields[class.bit]")[.](#2.sentence-1)
Unnamed bit-fields are not
members and cannot be initialized[.](#2.sentence-2)
An unnamed bit-field shall not be declared with a cv-qualified type[.](#2.sentence-3)
[*Note [2](#note-2)*:
An unnamed bit-field is useful for padding to conform to
externally-imposed layouts[.](#2.sentence-4)
— *end note*]
As a special case, an unnamed bit-field with a width of zero specifies
alignment of the next bit-field at an allocation unit boundary[.](#2.sentence-5)
Only
when declaring an unnamed bit-field may the width be zero[.](#2.sentence-6)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2920)
The address-of operator & shall not be applied to a bit-field,
so there are no pointers to bit-fields[.](#3.sentence-1)
A non-const reference shall not bind to a bit-field ([[dcl.init.ref]](dcl.init.ref "9.5.4References"))[.](#3.sentence-2)
[*Note [3](#note-3)*:
If the initializer for a reference of type const T& is
an lvalue that refers to a bit-field, the reference is bound to a
temporary initialized to hold the value of the bit-field; the reference
is not bound to the bit-field directly[.](#3.sentence-3)
See [[dcl.init.ref]](dcl.init.ref "9.5.4References")[.](#3.sentence-4)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2935)
If a value of integral type (other than bool) is stored
into a bit-field of width N and the value would be representable
in a hypothetical signed or unsigned integer type
with width N and the same signedness as the bit-field's type,
the original value and the value of the bit-field compare equal[.](#4.sentence-1)
If the value true or false is stored into a bit-field of
type bool of any size (including a one bit bit-field), the
original bool value and the value of the bit-field compare
equal[.](#4.sentence-2)
If a value of an enumeration type is stored into a bit-field of the
same type and the width is large
enough to hold all the values of that enumeration type ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations")),
the original value and the value of the bit-field compare equal[.](#4.sentence-3)
[*Example [1](#example-1)*: enum BOOL { FALSE=0, TRUE=1 };struct A { BOOL b:1;};
A a;void f() { a.b = TRUE; if (a.b == TRUE) // yields true{ /* ... */ }} — *end example*]

150
cppdraft/class/cdtor.md Normal file
View File

@@ -0,0 +1,150 @@
[class.cdtor]
# 11 Classes [[class]](./#class)
## 11.9 Initialization [[class.init]](class.init#class.cdtor)
### 11.9.5 Construction and destruction [class.cdtor]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6097)
For an object with a non-trivial constructor, referring to any non-static member
or base class of the object before the constructor begins execution results in
undefined behavior[.](#1.sentence-1)
For an object with a non-trivial destructor, referring to
any non-static member or base class of the object after the destructor finishes
execution results in undefined behavior[.](#1.sentence-2)
[*Example [1](#example-1)*: struct X { int i; };struct Y : X { Y(); }; // non-trivialstruct A { int a; };struct B : public A { int j; Y y; }; // non-trivialextern B bobj;
B* pb = &bobj; // OKint* p1 = &bobj.a; // undefined behavior: refers to base class memberint* p2 = &bobj.y.i; // undefined behavior: refers to member's member A* pa = &bobj; // undefined behavior: upcast to a base class type B bobj; // definition of bobjextern X xobj;int* p3 = &xobj.i; // OK, all constructors of X are trivial X xobj;
For another example,struct W { int j; };struct X : public virtual W { };struct Y {int* p;
X x;
Y() : p(&x.j) { // undefined, x is not yet constructed}};
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6137)
During the construction of an object,
if the value of any of its subobjects
or any element of its object representation
is accessed through a glvalue that is not obtained, directly or indirectly, from
the constructor'sthis pointer, the value thus obtained is unspecified[.](#2.sentence-1)
[*Example [2](#example-2)*: struct C;void no_opt(C*);
struct C {int c;
C() : c(0) { no_opt(this); }};
const C cobj;
void no_opt(C* cptr) {int i = cobj.c * 100; // value of cobj.c is unspecified cptr->c = 1;
cout << cobj.c * 100 // value of cobj.c is unspecified<< '\n';}extern struct D d;struct D { D(int a) : a(a), b(d.a) {}int a, b;};
D d = D(1); // value of d.b is unspecified — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6173)
To explicitly or implicitly convert a pointer (a glvalue) referring to
an object of classX to a pointer (reference) to a direct or indirect base classB ofX,
the construction ofX and the construction of all of its direct or indirect bases that directly or
indirectly derive fromB shall have started and the destruction of these classes shall not have
completed, otherwise the conversion results in undefined behavior[.](#3.sentence-1)
To form a pointer to (or access the value of) a direct non-static member of
an objectobj,
the construction ofobj shall have started and its destruction shall not have completed,
otherwise the computation of the pointer value (or accessing the member
value) results in undefined behavior[.](#3.sentence-2)
[*Example [3](#example-3)*: struct A { };struct B : virtual A { };struct C : B { };struct D : virtual A { D(A*); };struct X { X(A*); };
struct E : C, D, X { E() : D(this), // undefined behavior: upcast from E* to A* might use path E* → D* → A*// but D is not constructed// “D((C*)this)'' would be defined: E* → C* is defined because E() has started,// and C* → A* is defined because C is fully constructed X(this) {} // defined: upon construction of X, C/B/D/A sublattice is fully constructed}; — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6218)
Member functions, including virtual functions ([[class.virtual]](class.virtual "11.7.3Virtual functions")), can be called
during construction or destruction ([[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#4.sentence-1)
When a virtual function is called directly or indirectly from a constructor
or from a destructor,
including during the construction or destruction of the class's non-static data
members,
or during the evaluation of
a postcondition assertion of a constructor or
a precondition assertion of a destructor ([[dcl.contract.func]](dcl.contract.func "9.4.1General")),
and the object to which the call applies is the object (call it x) under construction or
destruction,
the function called is the
final overrider in the constructor's or destructor's class and not one
overriding it in a more-derived class[.](#4.sentence-2)
If the virtual function call uses an explicit class member access ([[expr.ref]](expr.ref "7.6.1.5Class member access"))
and the object expression refers to
the complete object of x or one of that object's base class subobjects
but not x or one of its base class subobjects, the behavior
is undefined[.](#4.sentence-3)
[*Example [4](#example-4)*: struct V {virtual void f(); virtual void g();};
struct A : virtual V {virtual void f();};
struct B : virtual V {virtual void g();
B(V*, A*);};
struct D : A, B {virtual void f(); virtual void g();
D() : B((A*)this, this) { }};
B::B(V* v, A* a) { f(); // calls V::f, not A::f g(); // calls B::g, not D::g v->g(); // v is base of B, the call is well-defined, calls B::g a->f(); // undefined behavior: a's type not a base of B} — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6273)
Thetypeid operator ([[expr.typeid]](expr.typeid "7.6.1.8Type identification")) can be used during construction or destruction ([[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#5.sentence-1)
Whentypeid is used in a constructor (including the[*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") or default member initializer ([[class.mem]](class.mem "11.4Class members"))
for a non-static data member)
or in a destructor, or used in a function called (directly or indirectly) from
a constructor or destructor, if the operand oftypeid refers to the object under construction or destruction,typeid yields thestd::type_info object representing the constructor or destructor's class[.](#5.sentence-2)
If the operand oftypeid refers to the object under construction or destruction and the static type of
the operand is neither the constructor or destructor's class nor one of its
bases, the behavior is undefined[.](#5.sentence-3)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6300)
dynamic_casts ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7Dynamic cast")) can be used during construction
or destruction ([[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#6.sentence-1)
When adynamic_cast is used in a constructor (including the[*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") or default member initializer
for a non-static data member)
or in a destructor, or used in a function called (directly or indirectly) from
a constructor or destructor, if the operand of thedynamic_cast refers to the object under construction or destruction, this object is
considered to be a most derived object that has the type of the constructor or
destructor's class[.](#6.sentence-2)
If the operand of thedynamic_cast refers to the object under construction or destruction and the static type of
the operand is not a pointer to or object of the constructor or destructor's
own class or one of its bases, thedynamic_cast results in undefined behavior[.](#6.sentence-3)
[*Example [5](#example-5)*: struct V {virtual void f();};
struct A : virtual V { };
struct B : virtual V { B(V*, A*);};
struct D : A, B { D() : B((A*)this, this) { }};
B::B(V* v, A* a) {typeid(*this); // type_info for Btypeid(*v); // well-defined: *v has type V, a base of B yields type_info for Btypeid(*a); // undefined behavior: type A not a base of Bdynamic_cast<B*>(v); // well-defined: v of type V*, V base of B results in B*dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B} — *end example*]

336
cppdraft/class/compare.md Normal file
View File

@@ -0,0 +1,336 @@
[class.compare]
# 11 Classes [[class]](./#class)
## 11.10 Comparisons [class.compare]
### [11.10.1](#default) Defaulted comparison operator functions [[class.compare.default]](class.compare.default)
[1](#default-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6562)
A defaulted comparison operator function ([[over.binary]](over.binary "12.4.3Binary operators"))
shall be a non-template function
that
- [(1.1)](#default-1.1)
is a non-static member or friend of some class C,
- [(1.2)](#default-1.2)
is defined as defaulted in C or in
a context where C is complete, and
- [(1.3)](#default-1.3)
either has
two parameters of type const C& or
two parameters of type C,
where the implicit object parameter (if any) is considered to be
the first parameter[.](#default-1.sentence-1)
Such a comparison operator function is termeda defaulted comparison operator function for class C[.](#default-1.sentence-2)
Name lookups and access checks in
the implicit definition ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions"))
of a comparison operator function
are performed from a context equivalent to
its [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]")[.](#default-1.sentence-3)
A definition of a comparison operator as
defaulted that appears in a class shall be the first declaration
of that function[.](#default-1.sentence-4)
[*Example [1](#default-example-1)*: struct S;bool operator==(S, S) = default; // error: S is not completestruct S {friend bool operator==(S, const S&) = default; // error: parameters of different types};enum E { };bool operator==(E, E) = default; // error: not a member or friend of a class — *end example*]
[2](#default-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6604)
A defaulted <=> or == operator function for class Cis defined as deleted if
any non-static data member of C is of reference type orC has variant members ([[class.union.anon]](class.union.anon "11.5.2Anonymous unions"))[.](#default-2.sentence-1)
[3](#default-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6612)
A binary operator expression a @ b is[*usable*](#def:usable,binary_operator_expression "11.10.1Defaulted comparison operator functions[class.compare.default]") if either
- [(3.1)](#default-3.1)
a or b is of class or enumeration type and
overload resolution ([[over.match]](over.match "12.2Overload resolution")) as applied to a @ b results in a usable candidate, or
- [(3.2)](#default-3.2)
neither a nor b is of class or enumeration type anda @ b is a valid expression[.](#default-3.sentence-1)
[4](#default-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6627)
If the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") does not explicitly declare
any member or friend named operator==,
an == operator function is declared implicitly
for each three-way comparison operator function
defined as defaulted in the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]"),
with the same access and [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]") and
in the same class scope as
the respective three-way comparison operator function,
except that the return type is replaced with bool and
the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is replaced with operator==[.](#default-4.sentence-1)
[*Note [1](#default-note-1)*:
Such an implicitly-declared == operator for a class X is defined as defaulted
in the definition of X and
has the same [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") and
trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") as
the respective three-way comparison operator[.](#default-4.sentence-2)
It is declared with friend, virtual, constexpr,
or consteval if
the three-way comparison operator function is so declared[.](#default-4.sentence-3)
If the three-way comparison operator function
has no [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]"),
the implicitly-declared == operator function
has an implicit exception specification ([[except.spec]](except.spec "14.5Exception specifications")) that
can differ from the implicit exception specification of
the three-way comparison operator function[.](#default-4.sentence-4)
— *end note*]
[*Example [2](#default-example-2)*: template<typename T> struct X {friend constexpr std::partial_ordering operator<=>(X, X) requires (sizeof(T) != 1) = default; // implicitly declares: friend constexpr bool operator==(X, X) requires (sizeof(T) != 1) = default;[[nodiscard]] virtual std::strong_ordering operator<=>(const X&) const = default; // implicitly declares: [[nodiscard]] virtual bool operator==(const X&) const = default;}; — *end example*]
[*Note [2](#default-note-2)*:
The == operator function is declared implicitly even if
the defaulted three-way comparison operator function
is defined as deleted[.](#default-4.sentence-5)
— *end note*]
[5](#default-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6673)
The direct base class subobjects of C,
in the order of their declaration in the [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]") of C,
followed by the non-static data members of C,
in the order of their declaration in the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of C,
form a list of subobjects[.](#default-5.sentence-1)
In that list, any subobject of array type is recursively expanded
to the sequence of its elements, in the order of increasing subscript[.](#default-5.sentence-2)
Let xi be an lvalue denoting the ith element
in the expanded list of subobjects for an object x (of length n),
where xi is
formed by a sequence of
derived-to-base conversions ([[over.best.ics]](over.best.ics "12.2.4.2Implicit conversion sequences")),
class member access expressions ([[expr.ref]](expr.ref "7.6.1.5Class member access")), and
array subscript expressions ([[expr.sub]](expr.sub "7.6.1.2Subscripting")) applied to x[.](#default-5.sentence-3)
### [11.10.2](#class.eq) Equality operator [[class.eq]](class.eq)
[1](#class.eq-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6693)
A defaulted equality operator function ([[over.binary]](over.binary "12.4.3Binary operators"))
shall have a declared return type bool[.](#class.eq-1.sentence-1)
[2](#class.eq-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6697)
A defaulted == operator function for a class C is defined as deleted
unless, for each xi in the expanded list of subobjects
for an object x of type C,xi == xi is usable ([[class.compare.default]](#default "11.10.1Defaulted comparison operator functions"))[.](#class.eq-2.sentence-1)
[3](#class.eq-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6705)
The return value of a defaulted == operator function
with parameters x and y is determined
by comparing corresponding elements xi and yi in the expanded lists of subobjects for x and y (in increasing index order)
until the first index i where xi == yi yields a result value which,
when contextually converted to bool, yields false[.](#class.eq-3.sentence-1)
The return value is false if such an index exists
and true otherwise[.](#class.eq-3.sentence-2)
[4](#class.eq-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6717)
[*Example [1](#class.eq-example-1)*: struct D {int i; friend bool operator==(const D& x, const D& y) = default; // OK, returns x.i == y.i}; — *end example*]
### [11.10.3](#class.spaceship) Three-way comparison [[class.spaceship]](class.spaceship)
[1](#class.spaceship-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6731)
The [*synthesized three-way comparison*](#def:three-way_comparison,synthesized "11.10.3Three-way comparison[class.spaceship]") of type R ([[cmp.categories]](cmp.categories "17.12.2Comparison category types"))
of glvalues a and b of the same type
is defined as follows:
- [(1.1)](#class.spaceship-1.1)
If a <=> b is usable ([[class.compare.default]](#default "11.10.1Defaulted comparison operator functions")) and
can be explicitly converted to R using static_cast,static_cast<R>(a <=> b)[.](#class.spaceship-1.1.sentence-1)
- [(1.2)](#class.spaceship-1.2)
Otherwise, if a <=> b is usable or
overload resolution for a <=> b is performed and
finds at least one viable candidate,
the synthesized three-way comparison is not defined[.](#class.spaceship-1.2.sentence-1)
- [(1.3)](#class.spaceship-1.3)
Otherwise, if R is not a comparison category type, or either
the expression a == b or the expression a < b is not usable,
the synthesized three-way comparison is not defined[.](#class.spaceship-1.3.sentence-1)
- [(1.4)](#class.spaceship-1.4)
Otherwise, if R is strong_ordering, thena == b ? strong_ordering::equal : a < b ? strong_ordering::less : strong_ordering::greater
- [(1.5)](#class.spaceship-1.5)
Otherwise, if R is weak_ordering, thena == b ? weak_ordering::equivalent : a < b ? weak_ordering::less : weak_ordering::greater
- [(1.6)](#class.spaceship-1.6)
Otherwise (when R is partial_ordering),a == b ? partial_ordering::equivalent : a < b ? partial_ordering::less : b < a ? partial_ordering::greater : partial_ordering::unordered
[*Note [1](#class.spaceship-note-1)*:
A synthesized three-way comparison is ill-formed
if overload resolution finds usable candidates
that do not otherwise meet the requirements implied by the defined expression[.](#class.spaceship-1.sentence-2)
— *end note*]
[2](#class.spaceship-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6786)
Let R be the declared return type of
a defaulted three-way comparison operator function, and
let xi be the elements of
the expanded list of subobjects for
an object x of type C[.](#class.spaceship-2.sentence-1)
- [(2.1)](#class.spaceship-2.1)
If R is auto, then
let cvi Ri be
the type of the expression xi <=> xi[.](#class.spaceship-2.1.sentence-1)
The operator function is defined as deleted
if that expression is not usable or
if Ri is not
a comparison category type ([[cmp.categories.pre]](cmp.categories.pre "17.12.2.1Preamble")) for any i[.](#class.spaceship-2.1.sentence-2)
The return type is deduced as
the common comparison type (see below) ofR0, R1, …, Rn−1[.](#class.spaceship-2.1.sentence-3)
- [(2.2)](#class.spaceship-2.2)
Otherwise, R shall not contain a placeholder type[.](#class.spaceship-2.2.sentence-1)
If the synthesized three-way comparison of type R between any objects xi and xi is not defined,
the operator function is defined as deleted[.](#class.spaceship-2.2.sentence-2)
[3](#class.spaceship-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6813)
The return value of type R of the defaulted three-way comparison operator function
with parameters x and y of the same type
is determined by comparing corresponding elementsxi and yi in the expanded lists of subobjects for x and y (in increasing index order)
until the first index i where
the synthesized three-way comparison of type R between xi and yi yields a result value vi where vi!=0,
contextually converted to bool, yields true[.](#class.spaceship-3.sentence-1)
The return value is a copy of vi if such an index exists andstatic_cast<R>(std::strong_ordering::equal) otherwise[.](#class.spaceship-3.sentence-2)
[4](#class.spaceship-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6830)
The [*common comparison type*](#def:common_comparison_type "11.10.3Three-way comparison[class.spaceship]") U of a possibly-empty list of n comparison category typesT0, T1, …, Tn−1 is defined as follows:
- [(4.1)](#class.spaceship-4.1)
If at least one Ti is std::partial_ordering,U is std::partial_ordering ([[cmp.partialord]](cmp.partialord "17.12.2.2Class partial_­ordering"))[.](#class.spaceship-4.1.sentence-1)
- [(4.2)](#class.spaceship-4.2)
Otherwise, if at least one Ti is std::weak_ordering,U is std::weak_ordering ([[cmp.weakord]](cmp.weakord "17.12.2.3Class weak_­ordering"))[.](#class.spaceship-4.2.sentence-1)
- [(4.3)](#class.spaceship-4.3)
Otherwise, U is std::strong_ordering ([[cmp.strongord]](cmp.strongord "17.12.2.4Class strong_­ordering"))[.](#class.spaceship-4.3.sentence-1)
[*Note [2](#class.spaceship-note-2)*:
In particular, this is the result when n is 0[.](#class.spaceship-4.3.sentence-2)
— *end note*]
### [11.10.4](#secondary) Secondary comparison operators [[class.compare.secondary]](class.compare.secondary)
[1](#secondary-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6855)
A [*secondary comparison operator*](#def:secondary_comparison_operator "11.10.4Secondary comparison operators[class.compare.secondary]") is
a relational operator ([[expr.rel]](expr.rel "7.6.9Relational operators")) or the != operator[.](#secondary-1.sentence-1)
A defaulted operator function ([[over.binary]](over.binary "12.4.3Binary operators"))
for a secondary comparison operator @ shall have a declared return type bool[.](#secondary-1.sentence-2)
[2](#secondary-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6863)
The operator function with parameters x and y is defined as deleted if
- [(2.1)](#secondary-2.1)
a first overload resolution ([[over.match]](over.match "12.2Overload resolution")),
as applied to x @ y,
* [(2.1.1)](#secondary-2.1.1)
does not result in a usable candidate, or
* [(2.1.2)](#secondary-2.1.2)
the selected candidate is not a rewritten candidate, or
- [(2.2)](#secondary-2.2)
a second overload resolution for
the expression resulting from the interpretation of x @ y using the selected rewritten candidate ([[over.match.oper]](over.match.oper "12.2.2.3Operators in expressions"))
does not result in a usable candidate
(for example, that expression might be (x <=> y) @ 0), or
- [(2.3)](#secondary-2.3)
x @ y cannot be implicitly converted to bool[.](#secondary-2.sentence-1)
In any of the two overload resolutions above,
the defaulted operator function is not considered as
a candidate for the @ operator[.](#secondary-2.sentence-2)
Otherwise, the operator function yields x @ y[.](#secondary-2.sentence-3)
[3](#secondary-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6892)
[*Example [1](#secondary-example-1)*: struct HasNoLessThan { };
struct C {friend HasNoLessThan operator<=>(const C&, const C&); bool operator<(const C&) const = default; // OK, function is deleted}; — *end example*]

View File

@@ -0,0 +1,135 @@
[class.compare.default]
# 11 Classes [[class]](./#class)
## 11.10 Comparisons [[class.compare]](class.compare#default)
### 11.10.1 Defaulted comparison operator functions [class.compare.default]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6562)
A defaulted comparison operator function ([[over.binary]](over.binary "12.4.3Binary operators"))
shall be a non-template function
that
- [(1.1)](#1.1)
is a non-static member or friend of some class C,
- [(1.2)](#1.2)
is defined as defaulted in C or in
a context where C is complete, and
- [(1.3)](#1.3)
either has
two parameters of type const C& or
two parameters of type C,
where the implicit object parameter (if any) is considered to be
the first parameter[.](#1.sentence-1)
Such a comparison operator function is termeda defaulted comparison operator function for class C[.](#1.sentence-2)
Name lookups and access checks in
the implicit definition ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions"))
of a comparison operator function
are performed from a context equivalent to
its [*function-body*](dcl.fct.def.general#nt:function-body "9.6.1General[dcl.fct.def.general]")[.](#1.sentence-3)
A definition of a comparison operator as
defaulted that appears in a class shall be the first declaration
of that function[.](#1.sentence-4)
[*Example [1](#example-1)*: struct S;bool operator==(S, S) = default; // error: S is not completestruct S {friend bool operator==(S, const S&) = default; // error: parameters of different types};enum E { };bool operator==(E, E) = default; // error: not a member or friend of a class — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6604)
A defaulted <=> or == operator function for class Cis defined as deleted if
any non-static data member of C is of reference type orC has variant members ([[class.union.anon]](class.union.anon "11.5.2Anonymous unions"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6612)
A binary operator expression a @ b is[*usable*](#def:usable,binary_operator_expression "11.10.1Defaulted comparison operator functions[class.compare.default]") if either
- [(3.1)](#3.1)
a or b is of class or enumeration type and
overload resolution ([[over.match]](over.match "12.2Overload resolution")) as applied to a @ b results in a usable candidate, or
- [(3.2)](#3.2)
neither a nor b is of class or enumeration type anda @ b is a valid expression[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6627)
If the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") does not explicitly declare
any member or friend named operator==,
an == operator function is declared implicitly
for each three-way comparison operator function
defined as defaulted in the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]"),
with the same access and [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]") and
in the same class scope as
the respective three-way comparison operator function,
except that the return type is replaced with bool and
the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") is replaced with operator==[.](#4.sentence-1)
[*Note [1](#note-1)*:
Such an implicitly-declared == operator for a class X is defined as defaulted
in the definition of X and
has the same [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") and
trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") as
the respective three-way comparison operator[.](#4.sentence-2)
It is declared with friend, virtual, constexpr,
or consteval if
the three-way comparison operator function is so declared[.](#4.sentence-3)
If the three-way comparison operator function
has no [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]"),
the implicitly-declared == operator function
has an implicit exception specification ([[except.spec]](except.spec "14.5Exception specifications")) that
can differ from the implicit exception specification of
the three-way comparison operator function[.](#4.sentence-4)
— *end note*]
[*Example [2](#example-2)*: template<typename T> struct X {friend constexpr std::partial_ordering operator<=>(X, X) requires (sizeof(T) != 1) = default; // implicitly declares: friend constexpr bool operator==(X, X) requires (sizeof(T) != 1) = default;[[nodiscard]] virtual std::strong_ordering operator<=>(const X&) const = default; // implicitly declares: [[nodiscard]] virtual bool operator==(const X&) const = default;}; — *end example*]
[*Note [2](#note-2)*:
The == operator function is declared implicitly even if
the defaulted three-way comparison operator function
is defined as deleted[.](#4.sentence-5)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6673)
The direct base class subobjects of C,
in the order of their declaration in the [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]") of C,
followed by the non-static data members of C,
in the order of their declaration in the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of C,
form a list of subobjects[.](#5.sentence-1)
In that list, any subobject of array type is recursively expanded
to the sequence of its elements, in the order of increasing subscript[.](#5.sentence-2)
Let xi be an lvalue denoting the ith element
in the expanded list of subobjects for an object x (of length n),
where xi is
formed by a sequence of
derived-to-base conversions ([[over.best.ics]](over.best.ics "12.2.4.2Implicit conversion sequences")),
class member access expressions ([[expr.ref]](expr.ref "7.6.1.5Class member access")), and
array subscript expressions ([[expr.sub]](expr.sub "7.6.1.2Subscripting")) applied to x[.](#5.sentence-3)

View File

@@ -0,0 +1,60 @@
[class.compare.secondary]
# 11 Classes [[class]](./#class)
## 11.10 Comparisons [[class.compare]](class.compare#secondary)
### 11.10.4 Secondary comparison operators [class.compare.secondary]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6855)
A [*secondary comparison operator*](#def:secondary_comparison_operator "11.10.4Secondary comparison operators[class.compare.secondary]") is
a relational operator ([[expr.rel]](expr.rel "7.6.9Relational operators")) or the != operator[.](#1.sentence-1)
A defaulted operator function ([[over.binary]](over.binary "12.4.3Binary operators"))
for a secondary comparison operator @ shall have a declared return type bool[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6863)
The operator function with parameters x and y is defined as deleted if
- [(2.1)](#2.1)
a first overload resolution ([[over.match]](over.match "12.2Overload resolution")),
as applied to x @ y,
* [(2.1.1)](#2.1.1)
does not result in a usable candidate, or
* [(2.1.2)](#2.1.2)
the selected candidate is not a rewritten candidate, or
- [(2.2)](#2.2)
a second overload resolution for
the expression resulting from the interpretation of x @ y using the selected rewritten candidate ([[over.match.oper]](over.match.oper "12.2.2.3Operators in expressions"))
does not result in a usable candidate
(for example, that expression might be (x <=> y) @ 0), or
- [(2.3)](#2.3)
x @ y cannot be implicitly converted to bool[.](#2.sentence-1)
In any of the two overload resolutions above,
the defaulted operator function is not considered as
a candidate for the @ operator[.](#2.sentence-2)
Otherwise, the operator function yields x @ y[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6892)
[*Example [1](#example-1)*: struct HasNoLessThan { };
struct C {friend HasNoLessThan operator<=>(const C&, const C&); bool operator<(const C&) const = default; // OK, function is deleted}; — *end example*]

254
cppdraft/class/conv.md Normal file
View File

@@ -0,0 +1,254 @@
[class.conv]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.conv)
### 11.4.8 Conversions [class.conv]
#### [11.4.8.1](#general) General [[class.conv.general]](class.conv.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2441)
Type conversions of class objects can be specified by constructors and
by conversion functions[.](#general-1.sentence-1)
These conversions are called[*user-defined conversions*](#def:conversion,user-defined "11.4.8.1General[class.conv.general]") and are used for implicit type conversions ([[conv]](conv "7.3Standard conversions")),
for initialization ([[dcl.init]](dcl.init "9.5Initializers")),
and for explicit type conversions ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"))[.](#general-1.sentence-2)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2455)
User-defined conversions are applied only where they are unambiguous ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"), [[class.conv.fct]](#fct "11.4.8.3Conversion functions"))[.](#general-2.sentence-1)
Conversions obey the access control rules ([[class.access]](class.access "11.8Member access control"))[.](#general-2.sentence-2)
Access control is applied after ambiguity resolution ([[basic.lookup]](basic.lookup "6.5Name lookup"))[.](#general-2.sentence-3)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2460)
[*Note [1](#general-note-1)*:
See [[over.match]](over.match "12.2Overload resolution") for a discussion of the use of conversions in function calls[.](#general-3.sentence-1)
— *end note*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2465)
At most one user-defined conversion (constructor or conversion function)
is implicitly applied to a single value[.](#general-4.sentence-1)
[*Example [1](#general-example-1)*: struct X {operator int();};
struct Y {operator X();};
Y a;int b = a; // error: no viable conversion (a.operator X().operator int() not considered)int c = X(a); // OK, a.operator X().operator int() — *end example*]
#### [11.4.8.2](#ctor) Conversion by constructor [[class.conv.ctor]](class.conv.ctor)
[1](#ctor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2488)
A constructor that is not explicit ([[dcl.fct.spec]](dcl.fct.spec "9.2.3Function specifiers"))
specifies a conversion from
the types of its parameters (if any)
to the type of its class[.](#ctor-1.sentence-1)
[*Example [1](#ctor-example-1)*:
[🔗](#:Jessie)
struct X { X(int);
X(const char*, int = 0);
X(int, int);};
void f(X arg) { X a = 1; // a = X(1) X b = "Jessie"; // b = X("Jessie",0) a = 2; // a = X(2) f(3); // f(X(3)) f({1, 2}); // f(X(1,2))} — *end example*]
[2](#ctor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2512)
[*Note [1](#ctor-note-1)*:
An explicit constructor constructs objects just like non-explicit
constructors, but does so only where the direct-initialization syntax ([[dcl.init]](dcl.init "9.5Initializers"))
or where casts ([[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)")) are explicitly
used; see also [[over.match.copy]](over.match.copy "12.2.2.5Copy-initialization of class by user-defined conversion")[.](#ctor-2.sentence-1)
A default constructor can be an explicit constructor; such a constructor
will be used to perform default-initialization
or value-initialization ([[dcl.init]](dcl.init "9.5Initializers"))[.](#ctor-2.sentence-2)
[*Example [2](#ctor-example-2)*: struct Z {explicit Z(); explicit Z(int); explicit Z(int, int);};
Z a; // OK, default-initialization performed Z b{}; // OK, direct initialization syntax used Z c = {}; // error: copy-list-initialization Z a1 = 1; // error: no implicit conversion Z a3 = Z(1); // OK, direct initialization syntax used Z a2(1); // OK, direct initialization syntax used Z* p = new Z(1); // OK, direct initialization syntax used Z a4 = (Z)1; // OK, explicit cast used Z a5 = static_cast<Z>(1); // OK, explicit cast used Z a6 = { 3, 4 }; // error: no implicit conversion — *end example*]
— *end note*]
#### [11.4.8.3](#fct) Conversion functions [[class.conv.fct]](class.conv.fct)
[conversion-function-id:](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]")
operator [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]")
[conversion-type-id:](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]")
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") [*conversion-declarator*](#nt:conversion-declarator "11.4.8.3Conversion functions[class.conv.fct]")opt
[conversion-declarator:](#nt:conversion-declarator "11.4.8.3Conversion functions[class.conv.fct]")
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1General[dcl.decl.general]") [*conversion-declarator*](#nt:conversion-declarator "11.4.8.3Conversion functions[class.conv.fct]")opt
[1](#fct-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2563)
A declaration
whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") has
an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") that is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") declares a [*conversion function*](#def:function,conversion "11.4.8.3Conversion functions[class.conv.fct]");
its [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") shall be
a function declarator ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) of the form
[*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1General[dcl.decl.general]") [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1General[dcl.decl.general]")
where the [*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1General[dcl.decl.general]") consists solely of
an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]"),
an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), and
optional surrounding parentheses, and
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") has one of the following forms:
- [(1.1)](#fct-1.1)
in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") that belongs to
the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of a class or class template
but is not a friend declaration ([[class.friend]](class.friend "11.8.4Friends")),
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]");
- [(1.2)](#fct-1.2)
otherwise, the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") whose [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]")[.](#fct-1.sentence-1)
[2](#fct-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2589)
A conversion function shall have no non-object parameters and
shall be a non-static member function of a class or class template X;
its declared return type is the [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") and
it specifies a conversion from X to
the type specified by the [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]"),
interpreted as a [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ([[dcl.name]](dcl.name "9.3.2Type names"))[.](#fct-2.sentence-1)
A [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a conversion function (if any) shall not be
a [*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]")[.](#fct-2.sentence-2)
[3](#fct-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2600)
[*Note [1](#fct-note-1)*:
A conversion function is never invoked for
implicit or explicit conversions of an object
to the same object type (or a reference to it),
to a base class of that type (or a reference to it),
or to cv void[.](#fct-3.sentence-1)
Even though never directly called to perform a conversion,
such conversion functions can be declared and can potentially
be reached through a call to a virtual conversion function in a base class[.](#fct-3.sentence-2)
— *end note*]
[*Example [1](#fct-example-1)*: struct X {operator int(); operator auto() -> short; // error: trailing return type};
void f(X a) {int i = int(a);
i = (int)a;
i = a;}
In all three cases the value assigned will be converted byX::operator int()[.](#fct-3.sentence-3)
— *end example*]
[4](#fct-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2628)
A conversion function may be explicit ([[dcl.fct.spec]](dcl.fct.spec "9.2.3Function specifiers")), in which case it is only considered as a user-defined conversion for direct-initialization ([[dcl.init]](dcl.init "9.5Initializers"))[.](#fct-4.sentence-1)
Otherwise, user-defined conversions are not restricted to use in assignments and initializations[.](#fct-4.sentence-2)
[*Example [2](#fct-example-2)*: class Y { };struct Z {explicit operator Y() const;};
void h(Z z) { Y y1(z); // OK, direct-initialization Y y2 = z; // error: no conversion function candidate for copy-initialization Y y3 = (Y)z; // OK, cast notation}void g(X a, X b) {int i = (a) ? 1+a : 0; int j = (a&&b) ? a+b : i; if (a) {}} — *end example*]
[5](#fct-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2652)
The[*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") shall not represent a function type nor an array type[.](#fct-5.sentence-1)
The[*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") in a[*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") is the longest sequence of
tokens that could possibly form a [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]")[.](#fct-5.sentence-2)
[*Note [2](#fct-note-2)*:
This prevents ambiguities between the declarator operator * and its expression
counterparts[.](#fct-5.sentence-3)
[*Example [3](#fct-example-3)*: &ac.operator int*i; // syntax error:// parsed as: &(ac.operator int *)i// not as: &(ac.operator int)*i
The * is the pointer declarator and not the multiplication operator[.](#fct-5.sentence-4)
— *end example*]
This rule also prevents ambiguities for attributes[.](#fct-5.sentence-5)
[*Example [4](#fct-example-4)*: operator int [[noreturn]] (); // error: noreturn attribute applied to a type — *end example*]
— *end note*]
[6](#fct-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2681)
[*Note [3](#fct-note-3)*:
A conversion function in a derived class hides only
conversion functions in base classes that convert to the same type[.](#fct-6.sentence-1)
A conversion function template with a dependent return type hides only
templates in base classes that correspond to it ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"));
otherwise, it hides and is hidden as a non-template function[.](#fct-6.sentence-2)
Function overload resolution ([[over.match.best]](over.match.best "12.2.4Best viable function")) selects
the best conversion function to perform the conversion[.](#fct-6.sentence-3)
[*Example [5](#fct-example-5)*: struct X {operator int();};
struct Y : X {operator char();};
void f(Y& a) {if (a) { // error: ambiguous between X::operator int() and Y::operator char()}} — *end example*]
— *end note*]
[7](#fct-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2709)
Conversion functions can be virtual[.](#fct-7.sentence-1)
[8](#fct-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2713)
A conversion function template shall not have a
deduced return type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))[.](#fct-8.sentence-1)
[*Example [6](#fct-example-6)*: struct S {operator auto() const { return 10; } // OKtemplate<class T>operator auto() const { return 1.2; } // error: conversion function template}; — *end example*]

View File

@@ -0,0 +1,49 @@
[class.conv.ctor]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.conv.ctor)
### 11.4.8 Conversions [[class.conv]](class.conv#ctor)
#### 11.4.8.2 Conversion by constructor [class.conv.ctor]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2488)
A constructor that is not explicit ([[dcl.fct.spec]](dcl.fct.spec "9.2.3Function specifiers"))
specifies a conversion from
the types of its parameters (if any)
to the type of its class[.](#1.sentence-1)
[*Example [1](#example-1)*:
[🔗](#:Jessie)
struct X { X(int);
X(const char*, int = 0);
X(int, int);};
void f(X arg) { X a = 1; // a = X(1) X b = "Jessie"; // b = X("Jessie",0) a = 2; // a = X(2) f(3); // f(X(3)) f({1, 2}); // f(X(1,2))} — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2512)
[*Note [1](#note-1)*:
An explicit constructor constructs objects just like non-explicit
constructors, but does so only where the direct-initialization syntax ([[dcl.init]](dcl.init "9.5Initializers"))
or where casts ([[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)")) are explicitly
used; see also [[over.match.copy]](over.match.copy "12.2.2.5Copy-initialization of class by user-defined conversion")[.](#2.sentence-1)
A default constructor can be an explicit constructor; such a constructor
will be used to perform default-initialization
or value-initialization ([[dcl.init]](dcl.init "9.5Initializers"))[.](#2.sentence-2)
[*Example [2](#example-2)*: struct Z {explicit Z(); explicit Z(int); explicit Z(int, int);};
Z a; // OK, default-initialization performed Z b{}; // OK, direct initialization syntax used Z c = {}; // error: copy-list-initialization Z a1 = 1; // error: no implicit conversion Z a3 = Z(1); // OK, direct initialization syntax used Z a2(1); // OK, direct initialization syntax used Z* p = new Z(1); // OK, direct initialization syntax used Z a4 = (Z)1; // OK, explicit cast used Z a5 = static_cast<Z>(1); // OK, explicit cast used Z a6 = { 3, 4 }; // error: no implicit conversion — *end example*]
— *end note*]

166
cppdraft/class/conv/fct.md Normal file
View File

@@ -0,0 +1,166 @@
[class.conv.fct]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.conv.fct)
### 11.4.8 Conversions [[class.conv]](class.conv#fct)
#### 11.4.8.3 Conversion functions [class.conv.fct]
[conversion-function-id:](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]")
operator [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]")
[conversion-type-id:](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]")
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1General[dcl.type.general]") [*conversion-declarator*](#nt:conversion-declarator "11.4.8.3Conversion functions[class.conv.fct]")opt
[conversion-declarator:](#nt:conversion-declarator "11.4.8.3Conversion functions[class.conv.fct]")
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1General[dcl.decl.general]") [*conversion-declarator*](#nt:conversion-declarator "11.4.8.3Conversion functions[class.conv.fct]")opt
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2563)
A declaration
whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") has
an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") that is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") declares a [*conversion function*](#def:function,conversion "11.4.8.3Conversion functions[class.conv.fct]");
its [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") shall be
a function declarator ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) of the form
[*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1General[dcl.decl.general]") [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1General[dcl.decl.general]")
where the [*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1General[dcl.decl.general]") consists solely of
an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]"),
an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"), and
optional surrounding parentheses, and
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") has one of the following forms:
- [(1.1)](#1.1)
in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") that belongs to
the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of a class or class template
but is not a friend declaration ([[class.friend]](class.friend "11.8.4Friends")),
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]");
- [(1.2)](#1.2)
otherwise, the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") whose [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]")[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2589)
A conversion function shall have no non-object parameters and
shall be a non-static member function of a class or class template X;
its declared return type is the [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") and
it specifies a conversion from X to
the type specified by the [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]"),
interpreted as a [*type-id*](dcl.name#nt:type-id "9.3.2Type names[dcl.name]") ([[dcl.name]](dcl.name "9.3.2Type names"))[.](#2.sentence-1)
A [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a conversion function (if any) shall not be
a [*defining-type-specifier*](dcl.type.general#nt:defining-type-specifier "9.2.9.1General[dcl.type.general]")[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2600)
[*Note [1](#note-1)*:
A conversion function is never invoked for
implicit or explicit conversions of an object
to the same object type (or a reference to it),
to a base class of that type (or a reference to it),
or to cv void[.](#3.sentence-1)
Even though never directly called to perform a conversion,
such conversion functions can be declared and can potentially
be reached through a call to a virtual conversion function in a base class[.](#3.sentence-2)
— *end note*]
[*Example [1](#example-1)*: struct X {operator int(); operator auto() -> short; // error: trailing return type};
void f(X a) {int i = int(a);
i = (int)a;
i = a;}
In all three cases the value assigned will be converted byX::operator int()[.](#3.sentence-3)
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2628)
A conversion function may be explicit ([[dcl.fct.spec]](dcl.fct.spec "9.2.3Function specifiers")), in which case it is only considered as a user-defined conversion for direct-initialization ([[dcl.init]](dcl.init "9.5Initializers"))[.](#4.sentence-1)
Otherwise, user-defined conversions are not restricted to use in assignments and initializations[.](#4.sentence-2)
[*Example [2](#example-2)*: class Y { };struct Z {explicit operator Y() const;};
void h(Z z) { Y y1(z); // OK, direct-initialization Y y2 = z; // error: no conversion function candidate for copy-initialization Y y3 = (Y)z; // OK, cast notation}void g(X a, X b) {int i = (a) ? 1+a : 0; int j = (a&&b) ? a+b : i; if (a) {}} — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2652)
The[*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") shall not represent a function type nor an array type[.](#5.sentence-1)
The[*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]") in a[*conversion-function-id*](#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") is the longest sequence of
tokens that could possibly form a [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3Conversion functions[class.conv.fct]")[.](#5.sentence-2)
[*Note [2](#note-2)*:
This prevents ambiguities between the declarator operator * and its expression
counterparts[.](#5.sentence-3)
[*Example [3](#example-3)*: &ac.operator int*i; // syntax error:// parsed as: &(ac.operator int *)i// not as: &(ac.operator int)*i
The * is the pointer declarator and not the multiplication operator[.](#5.sentence-4)
— *end example*]
This rule also prevents ambiguities for attributes[.](#5.sentence-5)
[*Example [4](#example-4)*: operator int [[noreturn]] (); // error: noreturn attribute applied to a type — *end example*]
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2681)
[*Note [3](#note-3)*:
A conversion function in a derived class hides only
conversion functions in base classes that convert to the same type[.](#6.sentence-1)
A conversion function template with a dependent return type hides only
templates in base classes that correspond to it ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"));
otherwise, it hides and is hidden as a non-template function[.](#6.sentence-2)
Function overload resolution ([[over.match.best]](over.match.best "12.2.4Best viable function")) selects
the best conversion function to perform the conversion[.](#6.sentence-3)
[*Example [5](#example-5)*: struct X {operator int();};
struct Y : X {operator char();};
void f(Y& a) {if (a) { // error: ambiguous between X::operator int() and Y::operator char()}} — *end example*]
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2709)
Conversion functions can be virtual[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2713)
A conversion function template shall not have a
deduced return type ([[dcl.spec.auto]](dcl.spec.auto "9.2.9.7Placeholder type specifiers"))[.](#8.sentence-1)
[*Example [6](#example-6)*: struct S {operator auto() const { return 10; } // OKtemplate<class T>operator auto() const { return 1.2; } // error: conversion function template}; — *end example*]

View File

@@ -0,0 +1,53 @@
[class.conv.general]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.conv.general)
### 11.4.8 Conversions [[class.conv]](class.conv#general)
#### 11.4.8.1 General [class.conv.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2441)
Type conversions of class objects can be specified by constructors and
by conversion functions[.](#1.sentence-1)
These conversions are called[*user-defined conversions*](#def:conversion,user-defined "11.4.8.1General[class.conv.general]") and are used for implicit type conversions ([[conv]](conv "7.3Standard conversions")),
for initialization ([[dcl.init]](dcl.init "9.5Initializers")),
and for explicit type conversions ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"))[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2455)
User-defined conversions are applied only where they are unambiguous ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"), [[class.conv.fct]](class.conv.fct "11.4.8.3Conversion functions"))[.](#2.sentence-1)
Conversions obey the access control rules ([[class.access]](class.access "11.8Member access control"))[.](#2.sentence-2)
Access control is applied after ambiguity resolution ([[basic.lookup]](basic.lookup "6.5Name lookup"))[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2460)
[*Note [1](#note-1)*:
See [[over.match]](over.match "12.2Overload resolution") for a discussion of the use of conversions in function calls[.](#3.sentence-1)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2465)
At most one user-defined conversion (constructor or conversion function)
is implicitly applied to a single value[.](#4.sentence-1)
[*Example [1](#example-1)*: struct X {operator int();};
struct Y {operator X();};
Y a;int b = a; // error: no viable conversion (a.operator X().operator int() not considered)int c = X(a); // OK, a.operator X().operator int() — *end example*]

View File

@@ -0,0 +1,309 @@
[class.copy.assign]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.copy.assign)
### 11.4.6 Copy/move assignment operator [class.copy.assign]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1787)
A user-declared [*copy*](#def:copy) assignment operator X::operator= is a
non-static non-template member function of class X with exactly one
non-object parameter of type X, X&, const X&,volatile X&, or const volatile X&[.](#1.sentence-1)[90](#footnote-90 "Because a template assignment operator or an assignment operator taking an rvalue reference parameter is never a copy assignment operator, the presence of such an assignment operator does not suppress the implicit declaration of a copy assignment operator. Such assignment operators participate in overload resolution with other assignment operators, including copy assignment operators, and, if selected, will be used to assign an object.")
[*Note [1](#note-1)*:
More than one form of copy assignment operator can be declared for a class[.](#1.sentence-2)
— *end note*]
[*Note [2](#note-2)*:
If a classX only has a copy assignment operator with a non-object parameter of typeX&,
an expression of type constX cannot be assigned to an object of typeX[.](#1.sentence-3)
[*Example [1](#example-1)*: struct X { X();
X& operator=(X&);};const X cx;
X x;void f() { x = cx; // error: X::operator=(X&) cannot assign cx into x} — *end example*]
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1835)
If the class definition does not explicitly declare a copy assignment operator,
one is declared [*implicitly*](#def:assignment_operator,copy,implicitly_declared "11.4.6Copy/move assignment operator[class.copy.assign]")[.](#2.sentence-1)
If the class definition declares a move
constructor or move assignment operator, the implicitly declared copy
assignment operator is defined as deleted; otherwise, it is
defaulted ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions"))[.](#2.sentence-2)
The latter case is deprecated if the class has a user-declared copy constructor
or a user-declared destructor ([[depr.impldec]](depr.impldec "D.6Implicit declaration of copy functions"))[.](#2.sentence-3)
The implicitly-declared copy assignment operator for a classX will have the formX& X::operator=(const X&) if
- [(2.1)](#2.1)
each direct base class B of X has a copy assignment operator whose non-object parameter is of typeconst B&, const volatile B&, or B, and
- [(2.2)](#2.2)
for all the non-static data members of X that are of a class type M (or array thereof),
each such class type has a copy assignment operator whose non-object parameter is of typeconst M&, const volatile M&,
or M[.](#2.sentence-4)[91](#footnote-91 "This implies that the reference parameter of the implicitly-declared copy assignment operator cannot bind to a volatile lvalue; see [diff.class].")
Otherwise, the implicitly-declared copy assignment operator
will have the formX& X::operator=(X&)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1875)
A user-declared move assignment operator X::operator= is
a non-static non-template member function of class X with exactly
one non-object parameter of type X&&, const X&&, volatile X&&, orconst volatile X&&[.](#3.sentence-1)
[*Note [3](#note-3)*:
More than one form of move assignment operator can be declared for a class[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1884)
If the definition of a class X does not explicitly declare a
move assignment operator, one
will be implicitly declared as defaulted if and only if
- [(4.1)](#4.1)
X does not have a user-declared copy constructor,
- [(4.2)](#4.2)
X does not have a user-declared move constructor,
- [(4.3)](#4.3)
X does not have a user-declared copy assignment operator, and
- [(4.4)](#4.4)
X does not have a user-declared destructor[.](#4.sentence-1)
[*Example [2](#example-2)*:
The class definitionstruct S {int a;
S& operator=(const S&) = default;}; will not have a default move assignment operator implicitly declared because the
copy assignment operator has been user-declared[.](#4.sentence-2)
The move assignment operator may
be explicitly defaulted[.](#4.sentence-3)
struct S {int a;
S& operator=(const S&) = default;
S& operator=(S&&) = default;}; — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1924)
The implicitly-declared move assignment operator for a class X will have the formX& X::operator=(X&&)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1930)
The implicitly-declared copy/move assignment operator for classX has the return typeX&[.](#6.sentence-1)
An implicitly-declared copy/move assignment operator is an
inline public member of its class[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1938)
A defaulted copy/move assignment operator for
class X is defined as deleted if X has:
- [(7.1)](#7.1)
a non-static data member of const non-class
type (or possibly multidimensional array thereof), or
- [(7.2)](#7.2)
a non-static data member of reference type, or
- [(7.3)](#7.3)
a direct non-static data member of class type M (or possibly multidimensional array thereof) or
a direct base class M that cannot be copied/moved because overload resolution ([[over.match]](over.match "12.2Overload resolution")),
as applied to find M's corresponding assignment operator,
either does not result in a usable candidate ([[over.match.general]](over.match.general "12.2.1General")) or,
in the case of a variant member, selects a non-trivial function[.](#7.sentence-1)
[*Note [4](#note-4)*:
A defaulted move assignment operator that is defined as deleted is ignored by
overload resolution ([[over.match]](over.match "12.2Overload resolution"), [[over.over]](over.over "12.3Address of an overload set"))[.](#7.sentence-2)
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1961)
Because a copy/move assignment operator is implicitly declared for a class
if not declared by the user,
a base class copy/move assignment operator is always hidden
by the corresponding assignment operator of a derived class ([[over.assign]](over.assign "12.4.3.2Simple assignment"))[.](#8.sentence-1)
[*Note [5](#note-5)*:
A [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]") in a derived class C that names an assignment operator from a base class
never suppresses the implicit declaration of
an assignment operator of C,
even if the base class assignment operator would be
a copy or move assignment operator
if declared as a member of C[.](#8.sentence-2)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1978)
A copy/move assignment operator for classX is
trivial
if it is not user-provided and if
- [(9.1)](#9.1)
classX has no virtual functions ([[class.virtual]](class.virtual "11.7.3Virtual functions"))
and no virtual base classes ([[class.mi]](class.mi "11.7.2Multiple base classes")), and
- [(9.2)](#9.2)
the assignment operator selected to copy/move each direct
base class subobject is trivial, and
- [(9.3)](#9.3)
for each non-static data member ofX that is of class type (or array thereof),
the assignment operator selected to copy/move that member is trivial;
otherwise the copy/move assignment operator is[*non-trivial*](#def:assignment_operator,copy,non-trivial "11.4.6Copy/move assignment operator[class.copy.assign]")[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2006)
An implicitly-defined ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions")) copy/move assignment operator is constexpr[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2009)
Before the defaulted copy/move assignment operator for a class is
implicitly defined,
all non-user-provided copy/move assignment operators for
its direct base classes and
its non-static data members are implicitly defined[.](#11.sentence-1)
[*Note [6](#note-6)*:
An implicitly-declared copy/move assignment operator has an
implied exception specification ([[except.spec]](except.spec "14.5Exception specifications"))[.](#11.sentence-2)
— *end note*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2020)
The implicitly-defined copy/move assignment operator for a
non-union class X performs memberwise copy/move assignment of its subobjects[.](#12.sentence-1)
The direct
base classes of X are assigned first, in the order of their declaration in the[*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]"), and then the immediate non-static data members ofX are assigned, in the order in which they were declared in the class
definition[.](#12.sentence-2)
Let x be either the parameter of the function or, for the move operator, an
xvalue referring to the parameter[.](#12.sentence-3)
Each subobject is assigned in the manner appropriate to its type:
- [(12.1)](#12.1)
if the subobject is of class type,
as if by a call to operator= with the subobject as the object expression
and the corresponding subobject of x as a single function argument
(as if by explicit qualification; that is,
ignoring any possible virtual overriding functions in more derived classes);
- [(12.2)](#12.2)
if the subobject is an array, each element is assigned,
in the manner appropriate to the element type;
- [(12.3)](#12.3)
if the subobject is of scalar type,
the built-in assignment operator is used[.](#12.sentence-4)
It is unspecified whether subobjects representing virtual base classes
are assigned more than once by the implicitly-defined copy/move assignment
operator[.](#12.sentence-5)
[*Example [3](#example-3)*: struct V { };struct A : virtual V { };struct B : virtual V { };struct C : B, A { };
It is unspecified whether the virtual base class subobjectV is assigned twice by the implicitly-defined copy/move assignment operator forC[.](#12.sentence-6)
— *end example*]
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2063)
The implicitly-defined copy/move assignment operator for a
union X copies the object representation ([[basic.types.general]](basic.types.general#term.object.representation "6.9.1General")) of X[.](#13.sentence-1)
If the source and destination of the assignment are not the same object, then
for each object nested within ([[intro.object]](intro.object "6.8.2Object model"))
the object that is the source of the copy,
a corresponding object o nested within the destination is created,
and the lifetime of o begins before the copy is performed[.](#13.sentence-2)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2072)
The implicitly-defined copy/move assignment operator for a class
returns the object for which the assignment operator is invoked,
that is, the object assigned to[.](#14.sentence-1)
[90)](#footnote-90)[90)](#footnoteref-90)
Because
a template assignment operator or an assignment operator
taking an rvalue reference parameter is never a copy assignment operator,
the presence of such an assignment operator does not suppress the
implicit declaration of a copy assignment operator[.](#footnote-90.sentence-1)
Such assignment operators
participate in overload resolution with other assignment operators, including
copy assignment operators, and, if selected, will be used to assign an object[.](#footnote-90.sentence-2)
[91)](#footnote-91)[91)](#footnoteref-91)
This implies that the reference parameter of the
implicitly-declared copy assignment operator cannot bind to avolatile lvalue; see [[diff.class]](diff.class "C.7.7[class]: classes")[.](#footnote-91.sentence-1)

301
cppdraft/class/copy/ctor.md Normal file
View File

@@ -0,0 +1,301 @@
[class.copy.ctor]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.copy.ctor)
### 11.4.5 Constructors [[class.ctor]](class.ctor#class.copy.ctor)
#### 11.4.5.3 Copy/move constructors [class.copy.ctor]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1477)
A non-template constructor for classX is
a
copy
constructor if its first parameter is of typeX&,const X&,volatile X& orconst volatile X&,
and either there are no other parameters
or else all other parameters have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#1.sentence-1)
[*Example [1](#example-1)*:
X::X(const X&) andX::X(X&,int=1) are copy constructors[.](#1.sentence-2)
struct X { X(int);
X(const X&, int = 1);};
X a(1); // calls X(int); X b(a, 0); // calls X(const X&, int); X c = b; // calls X(const X&, int); — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1512)
A non-template constructor for class X is a move constructor if its
first parameter is of type X&&, const X&&,volatile X&&, or const volatile X&&, and either there are
no other parameters or else all other parameters have default
arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#2.sentence-1)
[*Example [2](#example-2)*:
Y::Y(Y&&) is a move constructor[.](#2.sentence-2)
struct Y { Y(const Y&);
Y(Y&&);};extern Y f(int);
Y d(f(1)); // calls Y(Y&&) Y e = d; // calls Y(const Y&) — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1531)
[*Note [1](#note-1)*:
All forms of copy/move constructor can be declared for a class[.](#3.sentence-1)
[*Example [3](#example-3)*: struct X { X(const X&);
X(X&); // OK X(X&&);
X(const X&&); // OK, but possibly not sensible}; — *end example*]
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1546)
[*Note [2](#note-2)*:
If a classX only has a copy constructor with a parameter of typeX&,
an initializer of typeconstX orvolatileX cannot initialize an object of typecv X[.](#4.sentence-1)
[*Example [4](#example-4)*: struct X { X(); // default constructor X(X&); // copy constructor with a non-const parameter};const X cx;
X x = cx; // error: X::X(X&) cannot copy cx into x — *end example*]
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1572)
A declaration of a constructor for a classX is ill-formed if its first parameter is of typecv X and either there are no other parameters or else all other parameters have
default arguments[.](#5.sentence-1)
A member function template is never instantiated to
produce such a constructor signature[.](#5.sentence-2)
[*Example [5](#example-5)*: struct S {template<typename T> S(T);
S();};
S g;
void h() { S a(g); // does not instantiate the member template to produce S::S<S>(S);// uses the implicitly declared copy constructor} — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1597)
If the class definition does not explicitly declare a copy constructor,
a non-explicit one is declared [*implicitly*](#def:constructor,copy,implicitly_declared "11.4.5.3Copy/move constructors[class.copy.ctor]")[.](#6.sentence-1)
If the class definition declares a move
constructor or move assignment operator, the implicitly declared copy
constructor is defined as deleted; otherwise, it is
defaulted ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions"))[.](#6.sentence-2)
The latter case is deprecated if the class has a user-declared copy assignment
operator or a user-declared destructor ([[depr.impldec]](depr.impldec "D.6Implicit declaration of copy functions"))[.](#6.sentence-3)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1607)
The implicitly-declared copy constructor for a classX will have the formX::X(const X&) if each potentially constructed subobject of a class typeM (or array thereof)
has a copy constructor whose first parameter is of typeconstM& orconstvolatileM&[.](#7.sentence-1)[89](#footnote-89 "This implies that the reference parameter of the implicitly-declared copy constructor cannot bind to a volatile lvalue; see [diff.class].")
Otherwise, the implicitly-declared copy constructor will have the formX::X(X&)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1636)
If the definition of a class X does not explicitly declare
a move constructor, a non-explicit one will be
implicitly declared as defaulted if and only if
- [(8.1)](#8.1)
X does not have a user-declared copy constructor,
- [(8.2)](#8.2)
X does not have a user-declared copy assignment operator,
- [(8.3)](#8.3)
X does not have a user-declared move assignment operator, and
- [(8.4)](#8.4)
X does not have a user-declared destructor[.](#8.sentence-1)
[*Note [3](#note-3)*:
When the move constructor is not implicitly declared or explicitly supplied,
expressions that otherwise would have invoked the move constructor might instead invoke
a copy constructor[.](#8.sentence-2)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1661)
The implicitly-declared move constructor for class X will have the formX::X(X&&)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1667)
An implicitly-declared copy/move constructor is an
inline public member of its class[.](#10.sentence-1)
A defaulted copy/move constructor for a class X is defined as deleted ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3Deleted definitions")) if X has:
- [(10.1)](#10.1)
a potentially constructed subobject of type M (or possibly multidimensional array thereof) for which
overload resolution ([[over.match]](over.match "12.2Overload resolution")), as applied to find M's corresponding constructor,
either does not result in a usable candidate ([[over.match.general]](over.match.general "12.2.1General")) or,
in the case of a variant member, selects a non-trivial function,
- [(10.2)](#10.2)
any potentially constructed subobject of
class type M (or possibly multidimensional array thereof)
where M has
a destructor that is deleted or inaccessible from the defaulted
constructor, or,
- [(10.3)](#10.3)
for the copy constructor, a non-static data member of rvalue reference type[.](#10.sentence-2)
[*Note [4](#note-4)*:
A defaulted move constructor that is defined as deleted is ignored by overload
resolution ([[over.match]](over.match "12.2Overload resolution"), [[over.over]](over.over "12.3Address of an overload set"))[.](#10.sentence-3)
Such a constructor would otherwise interfere with initialization from
an rvalue which can use the copy constructor instead[.](#10.sentence-4)
— *end note*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1696)
A copy/move constructor for classX is
trivial
if it is not user-provided and if
- [(11.1)](#11.1)
classX has no virtual functions ([[class.virtual]](class.virtual "11.7.3Virtual functions"))
and no virtual base classes ([[class.mi]](class.mi "11.7.2Multiple base classes")), and
- [(11.2)](#11.2)
the constructor selected to copy/move each direct base class subobject is trivial, and
- [(11.3)](#11.3)
for each non-static data member ofX that is of class type (or array thereof),
the constructor selected to copy/move that member is trivial;
otherwise the copy/move constructor is[*non-trivial*](#def:constructor,copy,nontrivial "11.4.5.3Copy/move constructors[class.copy.ctor]")[.](#11.sentence-1)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1724)
[*Note [5](#note-5)*:
The copy/move constructor is implicitly defined even if the implementation elided
its odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule"), [[class.temporary]](class.temporary "6.8.7Temporary objects"))[.](#12.sentence-1)
— *end note*]
If an implicitly-defined ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions")) constructor would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers")),
the implicitly-defined
constructor is constexpr[.](#12.sentence-2)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1733)
Before the defaulted copy/move constructor for a class is
implicitly defined,
all non-user-provided copy/move constructors for its
potentially constructed subobjects
are implicitly defined[.](#13.sentence-1)
[*Note [6](#note-6)*:
An implicitly-declared copy/move constructor has an
implied exception specification ([[except.spec]](except.spec "14.5Exception specifications"))[.](#13.sentence-2)
— *end note*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1744)
The implicitly-defined copy/move constructor for a non-union classX performs a memberwise copy/move of its bases and members[.](#14.sentence-1)
[*Note [7](#note-7)*:
Default member initializers of non-static data members are ignored[.](#14.sentence-2)
— *end note*]
The order of initialization is the same as the order of initialization of bases
and members in a user-defined constructor (see [[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#14.sentence-3)
Let x be either the parameter of the constructor or, for the move constructor, an
xvalue referring to the parameter[.](#14.sentence-4)
Each base or non-static data member
is copied/moved in the manner appropriate to its type:
- [(14.1)](#14.1)
if the member is an array, each element is
direct-initialized with the corresponding subobject of x;
- [(14.2)](#14.2)
if a member m has rvalue reference type T&&, it is direct-initialized withstatic_cast<T&&>(x.m);
- [(14.3)](#14.3)
otherwise, the base or member is direct-initialized with the corresponding base or member of x[.](#14.sentence-5)
Virtual base class subobjects shall be initialized only once by
the implicitly-defined copy/move constructor (see [[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#14.sentence-6)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1774)
The implicitly-defined copy/move constructor for a unionX copies the object representation ([[basic.types.general]](basic.types.general#term.object.representation "6.9.1General")) of X[.](#15.sentence-1)
For each object nested within ([[intro.object]](intro.object "6.8.2Object model"))
the object that is the source of the copy,
a corresponding object o nested within the destination
is identified (if the object is a subobject) or created (otherwise),
and the lifetime of o begins before the copy is performed[.](#15.sentence-2)
[89)](#footnote-89)[89)](#footnoteref-89)
This implies that the reference parameter of the
implicitly-declared copy constructor
cannot bind to avolatile lvalue; see [[diff.class]](diff.class "C.7.7[class]: classes")[.](#footnote-89.sentence-1)

View File

@@ -0,0 +1,145 @@
[class.copy.elision]
# 11 Classes [[class]](./#class)
## 11.9 Initialization [[class.init]](class.init#class.copy.elision)
### 11.9.6 Copy/move elision [class.copy.elision]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6354)
When certain criteria are met, an implementation is
allowed to omit the creation of a class object from
a source object of the same type (ignoring cv-qualification),
even if the selected constructor and/or the
destructor for the object haveside effects[.](#1.sentence-1)
In such cases, the
implementation treats the source and target of the
omitted initialization as simply two different ways of
referring to the same object[.](#1.sentence-2)
If the first parameter of the
selected constructor is an rvalue reference to the object's type,
the destruction of that object occurs when the target would have been destroyed;
otherwise, the destruction occurs at the later of the times when the
two objects would have been destroyed without the
optimization[.](#1.sentence-3)
[*Note [1](#note-1)*:
Because only one object is destroyed instead of two,
and the creation of one object is omitted,
there is still one object destroyed for each one constructed[.](#1.sentence-4)
— *end note*]
This elision of object creation, called[*copy elision*](#def:copy_elision),
is permitted in the
following circumstances (which may be combined to
eliminate multiple copies):
- [(1.1)](#1.1)
in a return statement ([[stmt.return]](stmt.return "8.8.4The return statement")) in
a function with a class return type,
when the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is the name of a non-volatile
object o with automatic storage duration (other than a function parameter or a variable
introduced by the [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") of a[*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") ([[except.handle]](except.handle "14.4Handling an exception"))),
the copy-initialization of the result object can be
omitted by constructing o directly
into the function call's result object;
- [(1.2)](#1.2)
in a [*throw-expression*](expr.throw#nt:throw-expression "7.6.18Throwing an exception[expr.throw]") ([[expr.throw]](expr.throw "7.6.18Throwing an exception")), when the operand
is the name of a non-volatile object o with automatic storage duration
(other than a function parameter or
a variable introduced by
the [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") of a [*handler*](except.pre#nt:handler "14.1Preamble[except.pre]"))
that belongs to a scope that does not contain
the innermost enclosing [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") associated with a [*try-block*](except.pre#nt:try-block "14.1Preamble[except.pre]") (if there is one),
the copy-initialization of the exception object can be omitted by
constructing o directly into the exception object;
- [(1.3)](#1.3)
in a [coroutine](dcl.fct.def.coroutine "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"), a copy of a coroutine parameter
can be omitted and references to that copy replaced with references to the
corresponding parameter if the meaning of the program will be unchanged except for
the execution of a constructor and destructor for the parameter copy object;
- [(1.4)](#1.4)
when the [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") of a[*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") ([[except.handle]](except.handle "14.4Handling an exception")) declares an object o,
the copy-initialization of o can be omitted by treating
the [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") as an alias for the exception
object if the meaning of the program will be unchanged except for the execution
of constructors and destructors for the object declared by the[*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]")[.](#1.sentence-5)
[*Note [2](#note-2)*:
There cannot be a move from the exception object because it is
always an lvalue[.](#1.4.sentence-2)
— *end note*]
Copy elision is not permitted
where an expression is evaluated in a context
requiring a constant expression ([[expr.const]](expr.const "7.7Constant expressions"))
and in constant initialization ([[basic.start.static]](basic.start.static "6.10.3.2Static initialization"))[.](#1.sentence-6)
[*Note [3](#note-3)*:
It is possible that copy elision is performed
if the same expression
is evaluated in another context[.](#1.sentence-7)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6436)
[*Example [1](#example-1)*: class Thing {public: Thing(); ~Thing();
Thing(const Thing&);};
Thing f() { Thing t; return t;} Thing t2 = f();
struct A {void *p; constexpr A(): p(this) {}};
constexpr A g() { A loc; return loc;}constexpr A a; // well-formed, a.p points to aconstexpr A b = g(); // error: b.p would be dangling ([[expr.const]](expr.const "7.7Constant expressions"))void h() { A c = g(); // well-formed, c.p can point to c or be dangling}
Here the criteria for elision can eliminate
the copying of the object t with automatic storage duration
into the result object for the function call f(),
which is the non-local object t2[.](#2.sentence-1)
Effectively, the construction of t can be viewed as directly initializing t2,
and that object's destruction will occur at program exit[.](#2.sentence-2)
Adding a move constructor to Thing has the same effect, but it is the
move construction from the object with automatic storage duration to t2 that is elided[.](#2.sentence-3)
— *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6481)
[*Example [2](#example-2)*: class Thing {public: Thing(); ~Thing();
Thing(Thing&&);private: Thing(const Thing&);};
Thing f(bool b) { Thing t; if (b)throw t; // OK, Thing(Thing&&) used (or elided) to throw treturn t; // OK, Thing(Thing&&) used (or elided) to return t} Thing t2 = f(false); // OK, no extra copy/move performed, t2 constructed by call to fstruct Weird { Weird();
Weird(Weird&);};
Weird g(bool b) {static Weird w1;
Weird w2; if (b)return w1; // OK, uses Weird(Weird&)elsereturn w2; // error: w2 in this context is an xvalue}int& h(bool b, int i) {static int s; if (b)return s; // OKelsereturn i; // error: i is an xvalue}decltype(auto) h2(Thing t) {return t; // OK, t is an xvalue and h2's return type is Thing}decltype(auto) h3(Thing t) {return (t); // OK, (t) is an xvalue and h3's return type is Thing&&} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6534)
[*Example [3](#example-3)*: template<class T> void g(const T&);
template<class T> void f() { T x; try { T y; try { g(x); }catch (...) {if (/*...*/)throw x; // does not movethrow y; // moves} g(y); } catch(...) { g(x);
g(y); // error: y is not in scope}} — *end example*]

581
cppdraft/class/ctor.md Normal file
View File

@@ -0,0 +1,581 @@
[class.ctor]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.ctor)
### 11.4.5 Constructors [class.ctor]
#### [11.4.5.1](#general) General [[class.ctor.general]](class.ctor.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1240)
A [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") declares a [*constructor*](#def:constructor "11.4.5.1General[class.ctor.general]") if it is a
function declarator ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) of the form
[*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1General[dcl.decl.general]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") ) [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
where the [*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1General[dcl.decl.general]") consists solely of an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]"), an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"),
and optional surrounding parentheses, and the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") has
one of the following forms:
- [(1.1)](#general-1.1)
in a friend declaration ([[class.friend]](class.friend "11.8.4Friends")),
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") that names a constructor ([[class.qual]](class.qual "6.5.5.2Class members"));
- [(1.2)](#general-1.2)
otherwise, in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") that belongs to the[*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of a class or class template,
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is the
injected-class-name ([[class.pre]](class.pre "11.1Preamble")) of the immediately-enclosing entity;
- [(1.3)](#general-1.3)
otherwise, the[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") whose [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") is
the injected-class-name of its lookup context[.](#general-1.sentence-1)
Constructors do not have names[.](#general-1.sentence-2)
In a constructor declaration, each [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") in the optional[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") shall befriend,inline,constexpr,consteval, or
an [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]")[.](#general-1.sentence-3)
[*Example [1](#general-example-1)*: struct S { S(); // declares the constructor};
S::S() { } // defines the constructor — *end example*]
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1285)
A constructor is used to initialize objects of its class type[.](#general-2.sentence-1)
[*Note [1](#general-note-1)*:
Because constructors do not have names, they are never found during
unqualified name lookup; however an explicit type conversion using the functional
notation ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)")) will cause a constructor to be called to
initialize an object[.](#general-2.sentence-2)
The syntax looks like an explicit call of the constructor[.](#general-2.sentence-3)
— *end note*]
[*Example [2](#general-example-2)*: complex zz = complex(1,2.3);
cprint( complex(7.8,1.2) ); — *end example*]
[*Note [2](#general-note-2)*:
For initialization of objects of class type see [[class.init]](class.init "11.9Initialization")[.](#general-2.sentence-4)
— *end note*]
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1305)
An object created in this way is unnamed[.](#general-3.sentence-1)
[*Note [3](#general-note-3)*:
[[class.temporary]](class.temporary "6.8.7Temporary objects") describes the lifetime of temporary objects[.](#general-3.sentence-2)
— *end note*]
[*Note [4](#general-note-4)*:
Explicit constructor calls do not yield lvalues, see [[basic.lval]](basic.lval "7.2.1Value category")[.](#general-3.sentence-3)
— *end note*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1315)
[*Note [5](#general-note-5)*:
Some language constructs have special semantics when used during construction;
see [[class.base.init]](class.base.init "11.9.3Initializing bases and members") and [[class.cdtor]](class.cdtor "11.9.5Construction and destruction")[.](#general-4.sentence-1)
— *end note*]
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1322)
A constructor can be invoked for aconst,volatile orconstvolatile object[.](#general-5.sentence-1)
const andvolatile semantics ([[dcl.type.cv]](dcl.type.cv "9.2.9.2The cv-qualifiers")) are not applied on an object under construction[.](#general-5.sentence-2)
They come into effect when the constructor for the
most derived object ([[intro.object]](intro.object "6.8.2Object model")) ends[.](#general-5.sentence-3)
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1340)
The address of a constructor shall not be taken[.](#general-6.sentence-1)
[*Note [6](#general-note-6)*:
A return statement in the body of a constructor
cannot specify a return value ([[stmt.return]](stmt.return "8.8.4The return statement"))[.](#general-6.sentence-2)
— *end note*]
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1349)
A constructor shall not be a coroutine[.](#general-7.sentence-1)
[8](#general-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1352)
A constructor shall not have an explicit object parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#general-8.sentence-1)
#### [11.4.5.2](#class.default.ctor) Default constructors [[class.default.ctor]](class.default.ctor)
[1](#class.default.ctor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1357)
A [*default constructor*](#def:constructor,default "11.4.5.2Default constructors[class.default.ctor]") for a class X is a constructor of class X for which each parameter
that is not a function parameter pack
has a default argument
(including the case of a constructor with no parameters)[.](#class.default.ctor-1.sentence-1)
If there is no user-declared constructor or constructor template for classX,
a non-explicit constructor having no parameters is implicitly declared
as defaulted ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions"))[.](#class.default.ctor-1.sentence-2)
An implicitly-declared default constructor is an
inline public member of its class[.](#class.default.ctor-1.sentence-3)
[2](#class.default.ctor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1374)
A defaulted default constructor for class X is defined as deleted if
- [(2.1)](#class.default.ctor-2.1)
any non-static data member with no default member initializer ([[class.mem]](class.mem "11.4Class members")) is
of reference type,
- [(2.2)](#class.default.ctor-2.2)
X is a non-union class and
any non-variant non-static data member of const-qualified type
(or possibly multidimensional array thereof)
with no [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") is not const-default-constructible ([[dcl.init]](dcl.init "9.5Initializers")),
- [(2.3)](#class.default.ctor-2.3)
any non-variant potentially constructed subobject, except for a non-static data member
with a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]"),
has class type M (or possibly multidimensional array thereof)
and overload resolution ([[over.match]](over.match "12.2Overload resolution"))
as applied to find M's corresponding constructor
does not result in a usable candidate ([[over.match.general]](over.match.general "12.2.1General")), or
- [(2.4)](#class.default.ctor-2.4)
any potentially constructed subobject S has
class type M (or possibly multidimensional array thereof),M has
a destructor that is deleted or inaccessible from the defaulted default
constructor, and
either S is non-variant or S has a default member initializer[.](#class.default.ctor-2.sentence-1)
[3](#class.default.ctor-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1401)
A default constructor for a class X is[*trivial*](#def:constructor,default,trivial "11.4.5.2Default constructors[class.default.ctor]") if it is not user-provided and if
- [(3.1)](#class.default.ctor-3.1)
X has no virtual functions ([[class.virtual]](class.virtual "11.7.3Virtual functions")) and no virtual base
classes ([[class.mi]](class.mi "11.7.2Multiple base classes")), and
- [(3.2)](#class.default.ctor-3.2)
no non-static data member of X has
a default member initializer ([[class.mem]](class.mem "11.4Class members")), and
- [(3.3)](#class.default.ctor-3.3)
all the direct base classes of X have trivial default constructors, and
- [(3.4)](#class.default.ctor-3.4)
either X is a union or
for all the non-variant non-static data members of X that are of class
type (or array thereof), each such class has a trivial default constructor[.](#class.default.ctor-3.sentence-1)
Otherwise, the default constructor is[*non-trivial*](#def:constructor,default,non-trivial "11.4.5.2Default constructors[class.default.ctor]")[.](#class.default.ctor-3.sentence-2)
[4](#class.default.ctor-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1425)
If a default constructor of a union-like class X is trivial,
then for each union U that is either X or an anonymous union member of X,
if the first variant member, if any, of U has implicit-lifetime type ([[basic.types.general]](basic.types.general "6.9.1General")),
the default constructor of X begins the lifetime of that member
if it is not the active member of its union[.](#class.default.ctor-4.sentence-1)
[*Note [1](#class.default.ctor-note-1)*:
It is already the active member if U was value-initialized[.](#class.default.ctor-4.sentence-2)
— *end note*]
Otherwise,
an implicitly-defined ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions")) default constructor performs the set of
initializations of the class that would be performed by a user-written default
constructor for that class with no[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") ([[class.base.init]](class.base.init "11.9.3Initializing bases and members")) and an empty[*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")[.](#class.default.ctor-4.sentence-3)
If that user-written default constructor would be ill-formed,
the program is ill-formed[.](#class.default.ctor-4.sentence-4)
If that user-written default constructor would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers")),
the implicitly-defined
default constructor is constexpr[.](#class.default.ctor-4.sentence-5)
Before the defaulted default constructor for a class is
implicitly defined,
all the non-user-provided default constructors for its base classes and
its non-static data members are implicitly defined[.](#class.default.ctor-4.sentence-6)
[*Note [2](#class.default.ctor-note-2)*:
An implicitly-declared default constructor has an
exception specification ([[except.spec]](except.spec "14.5Exception specifications"))[.](#class.default.ctor-4.sentence-7)
An explicitly-defaulted definition might have an
implicit exception specification, see [[dcl.fct.def]](dcl.fct.def "9.6Function definitions")[.](#class.default.ctor-4.sentence-8)
— *end note*]
[5](#class.default.ctor-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1458)
[*Note [3](#class.default.ctor-note-3)*:
A default constructor is implicitly invoked to initialize
a class object when no initializer is specified ([[dcl.init.general]](dcl.init.general "9.5.1General"))[.](#class.default.ctor-5.sentence-1)
Such a default constructor needs to be accessible ([[class.access]](class.access "11.8Member access control"))[.](#class.default.ctor-5.sentence-2)
— *end note*]
[6](#class.default.ctor-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1466)
[*Note [4](#class.default.ctor-note-4)*:
[[class.base.init]](class.base.init "11.9.3Initializing bases and members") describes the order in which constructors for base
classes and non-static data members are called and
describes how arguments can be specified for the calls to these constructors[.](#class.default.ctor-6.sentence-1)
— *end note*]
#### [11.4.5.3](#class.copy.ctor) Copy/move constructors [[class.copy.ctor]](class.copy.ctor)
[1](#class.copy.ctor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1477)
A non-template constructor for classX is
a
copy
constructor if its first parameter is of typeX&,const X&,volatile X& orconst volatile X&,
and either there are no other parameters
or else all other parameters have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#class.copy.ctor-1.sentence-1)
[*Example [1](#class.copy.ctor-example-1)*:
X::X(const X&) andX::X(X&,int=1) are copy constructors[.](#class.copy.ctor-1.sentence-2)
struct X { X(int);
X(const X&, int = 1);};
X a(1); // calls X(int); X b(a, 0); // calls X(const X&, int); X c = b; // calls X(const X&, int); — *end example*]
[2](#class.copy.ctor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1512)
A non-template constructor for class X is a move constructor if its
first parameter is of type X&&, const X&&,volatile X&&, or const volatile X&&, and either there are
no other parameters or else all other parameters have default
arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#class.copy.ctor-2.sentence-1)
[*Example [2](#class.copy.ctor-example-2)*:
Y::Y(Y&&) is a move constructor[.](#class.copy.ctor-2.sentence-2)
struct Y { Y(const Y&);
Y(Y&&);};extern Y f(int);
Y d(f(1)); // calls Y(Y&&) Y e = d; // calls Y(const Y&) — *end example*]
[3](#class.copy.ctor-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1531)
[*Note [1](#class.copy.ctor-note-1)*:
All forms of copy/move constructor can be declared for a class[.](#class.copy.ctor-3.sentence-1)
[*Example [3](#class.copy.ctor-example-3)*: struct X { X(const X&);
X(X&); // OK X(X&&);
X(const X&&); // OK, but possibly not sensible}; — *end example*]
— *end note*]
[4](#class.copy.ctor-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1546)
[*Note [2](#class.copy.ctor-note-2)*:
If a classX only has a copy constructor with a parameter of typeX&,
an initializer of typeconstX orvolatileX cannot initialize an object of typecv X[.](#class.copy.ctor-4.sentence-1)
[*Example [4](#class.copy.ctor-example-4)*: struct X { X(); // default constructor X(X&); // copy constructor with a non-const parameter};const X cx;
X x = cx; // error: X::X(X&) cannot copy cx into x — *end example*]
— *end note*]
[5](#class.copy.ctor-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1572)
A declaration of a constructor for a classX is ill-formed if its first parameter is of typecv X and either there are no other parameters or else all other parameters have
default arguments[.](#class.copy.ctor-5.sentence-1)
A member function template is never instantiated to
produce such a constructor signature[.](#class.copy.ctor-5.sentence-2)
[*Example [5](#class.copy.ctor-example-5)*: struct S {template<typename T> S(T);
S();};
S g;
void h() { S a(g); // does not instantiate the member template to produce S::S<S>(S);// uses the implicitly declared copy constructor} — *end example*]
[6](#class.copy.ctor-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1597)
If the class definition does not explicitly declare a copy constructor,
a non-explicit one is declared [*implicitly*](#def:constructor,copy,implicitly_declared "11.4.5.3Copy/move constructors[class.copy.ctor]")[.](#class.copy.ctor-6.sentence-1)
If the class definition declares a move
constructor or move assignment operator, the implicitly declared copy
constructor is defined as deleted; otherwise, it is
defaulted ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions"))[.](#class.copy.ctor-6.sentence-2)
The latter case is deprecated if the class has a user-declared copy assignment
operator or a user-declared destructor ([[depr.impldec]](depr.impldec "D.6Implicit declaration of copy functions"))[.](#class.copy.ctor-6.sentence-3)
[7](#class.copy.ctor-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1607)
The implicitly-declared copy constructor for a classX will have the formX::X(const X&) if each potentially constructed subobject of a class typeM (or array thereof)
has a copy constructor whose first parameter is of typeconstM& orconstvolatileM&[.](#class.copy.ctor-7.sentence-1)[89](#footnote-89 "This implies that the reference parameter of the implicitly-declared copy constructor cannot bind to a volatile lvalue; see [diff.class].")
Otherwise, the implicitly-declared copy constructor will have the formX::X(X&)
[8](#class.copy.ctor-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1636)
If the definition of a class X does not explicitly declare
a move constructor, a non-explicit one will be
implicitly declared as defaulted if and only if
- [(8.1)](#class.copy.ctor-8.1)
X does not have a user-declared copy constructor,
- [(8.2)](#class.copy.ctor-8.2)
X does not have a user-declared copy assignment operator,
- [(8.3)](#class.copy.ctor-8.3)
X does not have a user-declared move assignment operator, and
- [(8.4)](#class.copy.ctor-8.4)
X does not have a user-declared destructor[.](#class.copy.ctor-8.sentence-1)
[*Note [3](#class.copy.ctor-note-3)*:
When the move constructor is not implicitly declared or explicitly supplied,
expressions that otherwise would have invoked the move constructor might instead invoke
a copy constructor[.](#class.copy.ctor-8.sentence-2)
— *end note*]
[9](#class.copy.ctor-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1661)
The implicitly-declared move constructor for class X will have the formX::X(X&&)
[10](#class.copy.ctor-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1667)
An implicitly-declared copy/move constructor is an
inline public member of its class[.](#class.copy.ctor-10.sentence-1)
A defaulted copy/move constructor for a class X is defined as deleted ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3Deleted definitions")) if X has:
- [(10.1)](#class.copy.ctor-10.1)
a potentially constructed subobject of type M (or possibly multidimensional array thereof) for which
overload resolution ([[over.match]](over.match "12.2Overload resolution")), as applied to find M's corresponding constructor,
either does not result in a usable candidate ([[over.match.general]](over.match.general "12.2.1General")) or,
in the case of a variant member, selects a non-trivial function,
- [(10.2)](#class.copy.ctor-10.2)
any potentially constructed subobject of
class type M (or possibly multidimensional array thereof)
where M has
a destructor that is deleted or inaccessible from the defaulted
constructor, or,
- [(10.3)](#class.copy.ctor-10.3)
for the copy constructor, a non-static data member of rvalue reference type[.](#class.copy.ctor-10.sentence-2)
[*Note [4](#class.copy.ctor-note-4)*:
A defaulted move constructor that is defined as deleted is ignored by overload
resolution ([[over.match]](over.match "12.2Overload resolution"), [[over.over]](over.over "12.3Address of an overload set"))[.](#class.copy.ctor-10.sentence-3)
Such a constructor would otherwise interfere with initialization from
an rvalue which can use the copy constructor instead[.](#class.copy.ctor-10.sentence-4)
— *end note*]
[11](#class.copy.ctor-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1696)
A copy/move constructor for classX is
trivial
if it is not user-provided and if
- [(11.1)](#class.copy.ctor-11.1)
classX has no virtual functions ([[class.virtual]](class.virtual "11.7.3Virtual functions"))
and no virtual base classes ([[class.mi]](class.mi "11.7.2Multiple base classes")), and
- [(11.2)](#class.copy.ctor-11.2)
the constructor selected to copy/move each direct base class subobject is trivial, and
- [(11.3)](#class.copy.ctor-11.3)
for each non-static data member ofX that is of class type (or array thereof),
the constructor selected to copy/move that member is trivial;
otherwise the copy/move constructor is[*non-trivial*](#def:constructor,copy,nontrivial "11.4.5.3Copy/move constructors[class.copy.ctor]")[.](#class.copy.ctor-11.sentence-1)
[12](#class.copy.ctor-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1724)
[*Note [5](#class.copy.ctor-note-5)*:
The copy/move constructor is implicitly defined even if the implementation elided
its odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule"), [[class.temporary]](class.temporary "6.8.7Temporary objects"))[.](#class.copy.ctor-12.sentence-1)
— *end note*]
If an implicitly-defined ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions")) constructor would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers")),
the implicitly-defined
constructor is constexpr[.](#class.copy.ctor-12.sentence-2)
[13](#class.copy.ctor-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1733)
Before the defaulted copy/move constructor for a class is
implicitly defined,
all non-user-provided copy/move constructors for its
potentially constructed subobjects
are implicitly defined[.](#class.copy.ctor-13.sentence-1)
[*Note [6](#class.copy.ctor-note-6)*:
An implicitly-declared copy/move constructor has an
implied exception specification ([[except.spec]](except.spec "14.5Exception specifications"))[.](#class.copy.ctor-13.sentence-2)
— *end note*]
[14](#class.copy.ctor-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1744)
The implicitly-defined copy/move constructor for a non-union classX performs a memberwise copy/move of its bases and members[.](#class.copy.ctor-14.sentence-1)
[*Note [7](#class.copy.ctor-note-7)*:
Default member initializers of non-static data members are ignored[.](#class.copy.ctor-14.sentence-2)
— *end note*]
The order of initialization is the same as the order of initialization of bases
and members in a user-defined constructor (see [[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#class.copy.ctor-14.sentence-3)
Let x be either the parameter of the constructor or, for the move constructor, an
xvalue referring to the parameter[.](#class.copy.ctor-14.sentence-4)
Each base or non-static data member
is copied/moved in the manner appropriate to its type:
- [(14.1)](#class.copy.ctor-14.1)
if the member is an array, each element is
direct-initialized with the corresponding subobject of x;
- [(14.2)](#class.copy.ctor-14.2)
if a member m has rvalue reference type T&&, it is direct-initialized withstatic_cast<T&&>(x.m);
- [(14.3)](#class.copy.ctor-14.3)
otherwise, the base or member is direct-initialized with the corresponding base or member of x[.](#class.copy.ctor-14.sentence-5)
Virtual base class subobjects shall be initialized only once by
the implicitly-defined copy/move constructor (see [[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#class.copy.ctor-14.sentence-6)
[15](#class.copy.ctor-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1774)
The implicitly-defined copy/move constructor for a unionX copies the object representation ([[basic.types.general]](basic.types.general#term.object.representation "6.9.1General")) of X[.](#class.copy.ctor-15.sentence-1)
For each object nested within ([[intro.object]](intro.object "6.8.2Object model"))
the object that is the source of the copy,
a corresponding object o nested within the destination
is identified (if the object is a subobject) or created (otherwise),
and the lifetime of o begins before the copy is performed[.](#class.copy.ctor-15.sentence-2)
[89)](#footnote-89)[89)](#footnoteref-89)
This implies that the reference parameter of the
implicitly-declared copy constructor
cannot bind to avolatile lvalue; see [[diff.class]](diff.class "C.7.7[class]: classes")[.](#footnote-89.sentence-1)

View File

@@ -0,0 +1,138 @@
[class.ctor.general]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.ctor.general)
### 11.4.5 Constructors [[class.ctor]](class.ctor#general)
#### 11.4.5.1 General [class.ctor.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1240)
A [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") declares a [*constructor*](#def:constructor "11.4.5.1General[class.ctor.general]") if it is a
function declarator ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) of the form
[*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1General[dcl.decl.general]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") ) [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
where the [*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1General[dcl.decl.general]") consists solely of an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]"), an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"),
and optional surrounding parentheses, and the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") has
one of the following forms:
- [(1.1)](#1.1)
in a friend declaration ([[class.friend]](class.friend "11.8.4Friends")),
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") that names a constructor ([[class.qual]](class.qual "6.5.5.2Class members"));
- [(1.2)](#1.2)
otherwise, in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") that belongs to the[*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of a class or class template,
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is the
injected-class-name ([[class.pre]](class.pre "11.1Preamble")) of the immediately-enclosing entity;
- [(1.3)](#1.3)
otherwise, the[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") whose [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") is
the injected-class-name of its lookup context[.](#1.sentence-1)
Constructors do not have names[.](#1.sentence-2)
In a constructor declaration, each [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") in the optional[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") shall befriend,inline,constexpr,consteval, or
an [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3Function specifiers[dcl.fct.spec]")[.](#1.sentence-3)
[*Example [1](#example-1)*: struct S { S(); // declares the constructor};
S::S() { } // defines the constructor — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1285)
A constructor is used to initialize objects of its class type[.](#2.sentence-1)
[*Note [1](#note-1)*:
Because constructors do not have names, they are never found during
unqualified name lookup; however an explicit type conversion using the functional
notation ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)")) will cause a constructor to be called to
initialize an object[.](#2.sentence-2)
The syntax looks like an explicit call of the constructor[.](#2.sentence-3)
— *end note*]
[*Example [2](#example-2)*: complex zz = complex(1,2.3);
cprint( complex(7.8,1.2) ); — *end example*]
[*Note [2](#note-2)*:
For initialization of objects of class type see [[class.init]](class.init "11.9Initialization")[.](#2.sentence-4)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1305)
An object created in this way is unnamed[.](#3.sentence-1)
[*Note [3](#note-3)*:
[[class.temporary]](class.temporary "6.8.7Temporary objects") describes the lifetime of temporary objects[.](#3.sentence-2)
— *end note*]
[*Note [4](#note-4)*:
Explicit constructor calls do not yield lvalues, see [[basic.lval]](basic.lval "7.2.1Value category")[.](#3.sentence-3)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1315)
[*Note [5](#note-5)*:
Some language constructs have special semantics when used during construction;
see [[class.base.init]](class.base.init "11.9.3Initializing bases and members") and [[class.cdtor]](class.cdtor "11.9.5Construction and destruction")[.](#4.sentence-1)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1322)
A constructor can be invoked for aconst,volatile orconstvolatile object[.](#5.sentence-1)
const andvolatile semantics ([[dcl.type.cv]](dcl.type.cv "9.2.9.2The cv-qualifiers")) are not applied on an object under construction[.](#5.sentence-2)
They come into effect when the constructor for the
most derived object ([[intro.object]](intro.object "6.8.2Object model")) ends[.](#5.sentence-3)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1340)
The address of a constructor shall not be taken[.](#6.sentence-1)
[*Note [6](#note-6)*:
A return statement in the body of a constructor
cannot specify a return value ([[stmt.return]](stmt.return "8.8.4The return statement"))[.](#6.sentence-2)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1349)
A constructor shall not be a coroutine[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1352)
A constructor shall not have an explicit object parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#8.sentence-1)

View File

@@ -0,0 +1,156 @@
[class.default.ctor]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.default.ctor)
### 11.4.5 Constructors [[class.ctor]](class.ctor#class.default.ctor)
#### 11.4.5.2 Default constructors [class.default.ctor]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1357)
A [*default constructor*](#def:constructor,default "11.4.5.2Default constructors[class.default.ctor]") for a class X is a constructor of class X for which each parameter
that is not a function parameter pack
has a default argument
(including the case of a constructor with no parameters)[.](#1.sentence-1)
If there is no user-declared constructor or constructor template for classX,
a non-explicit constructor having no parameters is implicitly declared
as defaulted ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions"))[.](#1.sentence-2)
An implicitly-declared default constructor is an
inline public member of its class[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1374)
A defaulted default constructor for class X is defined as deleted if
- [(2.1)](#2.1)
any non-static data member with no default member initializer ([[class.mem]](class.mem "11.4Class members")) is
of reference type,
- [(2.2)](#2.2)
X is a non-union class and
any non-variant non-static data member of const-qualified type
(or possibly multidimensional array thereof)
with no [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") is not const-default-constructible ([[dcl.init]](dcl.init "9.5Initializers")),
- [(2.3)](#2.3)
any non-variant potentially constructed subobject, except for a non-static data member
with a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]"),
has class type M (or possibly multidimensional array thereof)
and overload resolution ([[over.match]](over.match "12.2Overload resolution"))
as applied to find M's corresponding constructor
does not result in a usable candidate ([[over.match.general]](over.match.general "12.2.1General")), or
- [(2.4)](#2.4)
any potentially constructed subobject S has
class type M (or possibly multidimensional array thereof),M has
a destructor that is deleted or inaccessible from the defaulted default
constructor, and
either S is non-variant or S has a default member initializer[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1401)
A default constructor for a class X is[*trivial*](#def:constructor,default,trivial "11.4.5.2Default constructors[class.default.ctor]") if it is not user-provided and if
- [(3.1)](#3.1)
X has no virtual functions ([[class.virtual]](class.virtual "11.7.3Virtual functions")) and no virtual base
classes ([[class.mi]](class.mi "11.7.2Multiple base classes")), and
- [(3.2)](#3.2)
no non-static data member of X has
a default member initializer ([[class.mem]](class.mem "11.4Class members")), and
- [(3.3)](#3.3)
all the direct base classes of X have trivial default constructors, and
- [(3.4)](#3.4)
either X is a union or
for all the non-variant non-static data members of X that are of class
type (or array thereof), each such class has a trivial default constructor[.](#3.sentence-1)
Otherwise, the default constructor is[*non-trivial*](#def:constructor,default,non-trivial "11.4.5.2Default constructors[class.default.ctor]")[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1425)
If a default constructor of a union-like class X is trivial,
then for each union U that is either X or an anonymous union member of X,
if the first variant member, if any, of U has implicit-lifetime type ([[basic.types.general]](basic.types.general "6.9.1General")),
the default constructor of X begins the lifetime of that member
if it is not the active member of its union[.](#4.sentence-1)
[*Note [1](#note-1)*:
It is already the active member if U was value-initialized[.](#4.sentence-2)
— *end note*]
Otherwise,
an implicitly-defined ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2Explicitly-defaulted functions")) default constructor performs the set of
initializations of the class that would be performed by a user-written default
constructor for that class with no[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") ([[class.base.init]](class.base.init "11.9.3Initializing bases and members")) and an empty[*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")[.](#4.sentence-3)
If that user-written default constructor would be ill-formed,
the program is ill-formed[.](#4.sentence-4)
If that user-written default constructor would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers")),
the implicitly-defined
default constructor is constexpr[.](#4.sentence-5)
Before the defaulted default constructor for a class is
implicitly defined,
all the non-user-provided default constructors for its base classes and
its non-static data members are implicitly defined[.](#4.sentence-6)
[*Note [2](#note-2)*:
An implicitly-declared default constructor has an
exception specification ([[except.spec]](except.spec "14.5Exception specifications"))[.](#4.sentence-7)
An explicitly-defaulted definition might have an
implicit exception specification, see [[dcl.fct.def]](dcl.fct.def "9.6Function definitions")[.](#4.sentence-8)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1458)
[*Note [3](#note-3)*:
A default constructor is implicitly invoked to initialize
a class object when no initializer is specified ([[dcl.init.general]](dcl.init.general "9.5.1General"))[.](#5.sentence-1)
Such a default constructor needs to be accessible ([[class.access]](class.access "11.8Member access control"))[.](#5.sentence-2)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1466)
[*Note [4](#note-4)*:
[[class.base.init]](class.base.init "11.9.3Initializing bases and members") describes the order in which constructors for base
classes and non-static data members are called and
describes how arguments can be specified for the calls to these constructors[.](#6.sentence-1)
— *end note*]

763
cppdraft/class/derived.md Normal file
View File

@@ -0,0 +1,763 @@
[class.derived]
# 11 Classes [[class]](./#class)
## 11.7 Derived classes [class.derived]
### [11.7.1](#general) General [[class.derived.general]](class.derived.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3511)
A list of base classes can be specified in a class definition using
the notation:
[base-clause:](#nt:base-clause "11.7.1General[class.derived.general]")
: [*base-specifier-list*](#nt:base-specifier-list "11.7.1General[class.derived.general]")
[base-specifier-list:](#nt:base-specifier-list "11.7.1General[class.derived.general]")
[*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") ...opt
[*base-specifier-list*](#nt:base-specifier-list "11.7.1General[class.derived.general]") , [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") ...opt
[base-specifier:](#nt:base-specifier "11.7.1General[class.derived.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt virtual [*access-specifier*](#nt:access-specifier "11.7.1General[class.derived.general]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*access-specifier*](#nt:access-specifier "11.7.1General[class.derived.general]") virtualopt [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[class-or-decltype:](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")
[access-specifier:](#nt:access-specifier "11.7.1General[class.derived.general]")
private
protected
public
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]")[.](#general-1.sentence-2)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3554)
The component names of a [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]") are those of its[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"),[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]"), and/or[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")[.](#general-2.sentence-1)
A [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]") shall denote
a (possibly cv-qualified) class type that is not
an incompletely defined class ([[class.mem]](class.mem "11.4Class members"));
any cv-qualifiers are ignored[.](#general-2.sentence-2)
The class denoted by the [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]") of
a [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") is called a[*direct base class*](#def:base_class,direct "11.7.1General[class.derived.general]") for the class being defined;
for each such [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]"),
the corresponding [*direct base class relationship*](#def:relationship,direct_base_class "11.7.1General[class.derived.general]") is the ordered pair (D, B)
where D is the class being defined andB is the direct base class[.](#general-2.sentence-3)
The lookup for the component name of
the [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") is type-only ([[basic.lookup]](basic.lookup "6.5Name lookup"))[.](#general-2.sentence-4)
A class B is a
base class of a class D if it is a direct base class ofD or a direct base class of one of D's base classes[.](#general-2.sentence-5)
A class is an [*indirect base class*](#def:base_class,indirect "11.7.1General[class.derived.general]") of another if it is a base
class but not a direct base class[.](#general-2.sentence-6)
A class is said to be (directly or
indirectly) [*derived*](#def:derived) from its (direct or indirect) base
classes[.](#general-2.sentence-7)
[*Note [1](#general-note-1)*:
See [[class.access]](class.access "11.8Member access control") for the meaning of[*access-specifier*](#nt:access-specifier "11.7.1General[class.derived.general]")[.](#general-2.sentence-8)
— *end note*]
Members of a base class are also members of the derived class[.](#general-2.sentence-9)
[*Note [2](#general-note-2)*:
Constructors of a base class can be explicitly inherited ([[namespace.udecl]](namespace.udecl "9.10The using declaration"))[.](#general-2.sentence-10)
Base class members can be referred to in
expressions in the same manner as other members of the derived class,
unless their names are hidden or ambiguous ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))[.](#general-2.sentence-11)
The scope resolution operator :: ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names")) can be used
to refer to a direct or indirect base member explicitly,
even if it is hidden in the derived class[.](#general-2.sentence-12)
A derived class can itself serve as a base class subject to access
control; see [[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members")[.](#general-2.sentence-13)
A pointer to a derived class can be
implicitly converted to a pointer to an accessible unambiguous base
class ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions"))[.](#general-2.sentence-14)
An lvalue of a derived class type can be bound
to a reference to an accessible unambiguous base
class ([[dcl.init.ref]](dcl.init.ref "9.5.4References"))[.](#general-2.sentence-15)
— *end note*]
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3609)
The [*base-specifier-list*](#nt:base-specifier-list "11.7.1General[class.derived.general]") specifies the type of the[*base class subobjects*](#def:base_class_subobjects) contained in an
object of the derived class type[.](#general-3.sentence-1)
[*Example [1](#general-example-1)*: struct Base {int a, b, c;};
struct Derived : Base {int b;};
struct Derived2 : Derived {int c;};
Here, an object of class Derived2 will have a subobject of classDerived which in turn will have a subobject of classBase[.](#general-3.sentence-2)
— *end example*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3637)
A [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") followed by an ellipsis is a pack
expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#general-4.sentence-1)
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3641)
The order in which the base class subobjects are allocated in the most
derived object ([[intro.object]](intro.object "6.8.2Object model")) is unspecified[.](#general-5.sentence-1)
[*Note [3](#general-note-3)*:
A derived class and its base class subobjects can be represented by a
directed acyclic graph (DAG) where an arrow means “directly derived
from” (see Figure [3](#fig:class.dag))[.](#general-5.sentence-2)
An arrow need not have a physical representation in memory[.](#general-5.sentence-3)
A DAG of subobjects is often referred to as a “subobject lattice”[.](#general-5.sentence-4)
— *end note*]
![SVG Image](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzlwdCIgaGVpZ2h0PSIxNDBwdCIgdmlld0JveD0iMC4wMCAwLjAwIDc5LjAwIDE0MC4wMCI+CjxnIGNsYXNzPSJncmFwaCI+CmRhZwoKPGcgY2xhc3M9Im5vZGUiPgpCYXNlCkJhc2UKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpEZXJpdmVkMQpEZXJpdmVkMQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkRlcml2ZWQxLSZndDtCYXNlCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0zNS41LC03Ni40MUMzNS41LC04My4zIDM1LjUsLTkyLjkgMzUuNSwtMTAxLjQzIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpEZXJpdmVkMgpEZXJpdmVkMgo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkRlcml2ZWQyLSZndDtEZXJpdmVkMQo8cGF0aCBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBkPSJNMzUuNSwtMjAuNDFDMzUuNSwtMjcuMyAzNS41LC0zNi45IDM1LjUsLTQ1LjQzIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==)
Figure [3](#fig:class.dag) — Directed acyclic graph [[fig:class.dag]](./fig:class.dag)
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3661)
[*Note [4](#general-note-4)*:
Initialization of objects representing base classes can be specified in
constructors; see [[class.base.init]](class.base.init "11.9.3Initializing bases and members")[.](#general-6.sentence-1)
— *end note*]
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3667)
[*Note [5](#general-note-5)*:
A base class subobject can have a layout different
from the layout of a most derived object of the same type[.](#general-7.sentence-1)
A base class
subobject can have a polymorphic behavior ([[class.cdtor]](class.cdtor "11.9.5Construction and destruction"))
different from the polymorphic behavior of a most derived object of the
same type[.](#general-7.sentence-2)
A base class subobject can be of zero size;
however, two subobjects that have the same class type and that belong to
the same most derived object cannot be allocated at the same
address ([[intro.object]](intro.object "6.8.2Object model"))[.](#general-7.sentence-3)
— *end note*]
### [11.7.2](#class.mi) Multiple base classes [[class.mi]](class.mi)
[1](#class.mi-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3683)
A class can be derived from any number of base classes[.](#class.mi-1.sentence-1)
[*Note [1](#class.mi-note-1)*:
The use of more than one direct base class is often called multiple inheritance[.](#class.mi-1.sentence-2)
— *end note*]
[*Example [1](#class.mi-example-1)*: class A { /* ... */ };class B { /* ... */ };class C { /* ... */ };class D : public A, public B, public C { /* ... */ }; — *end example*]
[2](#class.mi-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3697)
[*Note [2](#class.mi-note-2)*:
The order of derivation is not significant except as specified by the
semantics of initialization by constructor ([[class.base.init]](class.base.init "11.9.3Initializing bases and members")),
cleanup ([[class.dtor]](class.dtor "11.4.7Destructors")), and storage
layout ([[class.mem]](class.mem "11.4Class members"), [[class.access.spec]](class.access.spec "11.8.2Access specifiers"))[.](#class.mi-2.sentence-1)
— *end note*]
[3](#class.mi-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3707)
A class shall not be specified as a direct base class of a derived class
more than once[.](#class.mi-3.sentence-1)
[*Note [3](#class.mi-note-3)*:
A class can be an indirect base class more than once and can be a direct
and an indirect base class[.](#class.mi-3.sentence-2)
There are limited things that can be done
with such a class;
lookup that finds its non-static data members and member functions
in the scope of the derived class will be ambiguous[.](#class.mi-3.sentence-3)
However, the static members, enumerations and types can be
unambiguously referred to[.](#class.mi-3.sentence-4)
— *end note*]
[*Example [2](#class.mi-example-2)*: class X { /* ... */ };class Y : public X, public X { /* ... */ }; // errorclass L { public: int next; /* ... */ };class A : public L { /* ... */ };class B : public L { /* ... */ };class C : public A, public B { void f(); /* ... */ }; // well-formedclass D : public A, public L { void f(); /* ... */ }; // well-formed — *end example*]
[4](#class.mi-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3734)
A base class specifier that does not contain the keywordvirtual specifies a [*non-virtual base class*](#def:base_class,non-virtual "11.7.2Multiple base classes[class.mi]")[.](#class.mi-4.sentence-1)
A base
class specifier that contains the keyword virtual specifies a[*virtual base class*](#def:base_class,virtual "11.7.2Multiple base classes[class.mi]")[.](#class.mi-4.sentence-2)
For each distinct occurrence of a
non-virtual base class in the class lattice of the most derived class,
the most derived object ([[intro.object]](intro.object "6.8.2Object model")) shall contain a
corresponding distinct base class subobject of that type[.](#class.mi-4.sentence-3)
For each
distinct base class that is specified virtual, the most derived object
shall contain a single base class subobject of that type[.](#class.mi-4.sentence-4)
[5](#class.mi-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3746)
[*Note [4](#class.mi-note-4)*:
For an object of class type C, each distinct occurrence of a
(non-virtual) base class L in the class lattice of C corresponds one-to-one with a distinct L subobject within the
object of type C[.](#class.mi-5.sentence-1)
Given the class C defined above, an
object of class C will have two subobjects of class L as
shown in Figure [4](#fig:class.nonvirt)[.](#class.mi-5.sentence-2)
![SVG Image](data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwLjAwIDAuMDAgMjI0LjAwIDE0MC4wMCIgaGVpZ2h0PSIxNDBwdCIgd2lkdGg9IjIyNHB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4Kbm9udmlydAoKPGcgY2xhc3M9Im5vZGUiPgpMMQpMCjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KTDIKTAo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+CkEKQQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkEtJmd0O0wxCjxwYXRoIHN0cm9rZT0iYmxhY2siIGQ9Ik0yNywtNzYuNDFDMjcsLTgzLjMgMjcsLTkyLjkgMjcsLTEwMS40MyIgZmlsbD0ibm9uZSIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQgpCCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQi0mZ3Q7TDIKPHBhdGggZmlsbD0ibm9uZSIgZD0iTTE4OSwtNzYuNDFDMTg5LC04My4zIDE4OSwtOTIuOSAxODksLTEwMS40MyIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQwpDCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQy0mZ3Q7QQo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNOTQuMjYsLTIwLjE2QzgxLjg1LC0yOC40MyA2My4zNywtNDAuNzUgNDguOTIsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpDLSZndDtCCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==)
Figure [4](#fig:class.nonvirt) — Non-virtual base [[fig:class.nonvirt]](./fig:class.nonvirt)
In such lattices, explicit qualification can be used to specify which
subobject is meant[.](#class.mi-5.sentence-3)
The body of function C::f can refer to the
member next of each L subobject:void C::f() { A::next = B::next; } // well-formed
Without the A:: or B:: qualifiers, the definition ofC::f above would be ill-formed because of
ambiguity ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))[.](#class.mi-5.sentence-5)
— *end note*]
[6](#class.mi-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3772)
[*Note [5](#class.mi-note-5)*:
In contrast, consider the case with a virtual base class:class V { /* ... */ };class A : virtual public V { /* ... */ };class B : virtual public V { /* ... */ };class C : public A, public B { /* ... */ };
![SVG Image](data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwLjAwIDAuMDAgMjI0LjAwIDE0MC4wMCIgaGVpZ2h0PSIxNDBwdCIgd2lkdGg9IjIyNHB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4KdmlydAoKPGcgY2xhc3M9Im5vZGUiPgpWClYKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpBCkEKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpBLSZndDtWCjxwYXRoIGQ9Ik00MC43NCwtNzYuMTZDNTMuMTUsLTg0LjQzIDcxLjYzLC05Ni43NSA4Ni4wOCwtMTA2LjM4IiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpCCkIKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpCLSZndDtWCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xNzUuMjYsLTc2LjE2QzE2Mi44NSwtODQuNDMgMTQ0LjM3LC05Ni43NSAxMjkuOTIsLTEwNi4zOCIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQwpDCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQy0mZ3Q7QQo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNOTQuMjYsLTIwLjE2QzgxLjg1LC0yOC40MyA2My4zNywtNDAuNzUgNDguOTIsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpDLSZndDtCCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==)
Figure [5](#fig:class.virt) — Virtual base [[fig:class.virt]](./fig:class.virt)
For an object c of class type C, a single subobject of
type V is shared by every base class subobject of c that has avirtual base class of type V[.](#class.mi-6.sentence-1)
Given the class C defined above, an object of class C will have one subobject of
class V, as shown in Figure [5](#fig:class.virt)[.](#class.mi-6.sentence-2)
— *end note*]
[7](#class.mi-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3795)
[*Note [6](#class.mi-note-6)*:
A class can have both virtual and non-virtual base classes of a given
type[.](#class.mi-7.sentence-1)
class B { /* ... */ };class X : virtual public B { /* ... */ };class Y : virtual public B { /* ... */ };class Z : public B { /* ... */ };class AA : public X, public Y, public Z { /* ... */ };
For an object of class AA, all virtual occurrences of
base class B in the class lattice of AA correspond to a
single B subobject within the object of type AA, and
every other occurrence of a (non-virtual) base class B in the
class lattice of AA corresponds one-to-one with a distinctB subobject within the object of type AA[.](#class.mi-7.sentence-2)
Given the
class AA defined above, class AA has two subobjects of
class B: Z's B and the virtual B shared
by X and Y, as shown in Figure [6](#fig:class.virtnonvirt)[.](#class.mi-7.sentence-3)
![SVG Image](data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwLjAwIDAuMDAgMzg2LjAwIDE0MC4wMCIgaGVpZ2h0PSIxNDBwdCIgd2lkdGg9IjM4NnB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4KdmlydG5vbnZpcnQKCjxnIGNsYXNzPSJub2RlIj4KQjEKQgo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+CkIyCkIKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpBQQpBQQo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+ClgKWAo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkFBLSZndDtYCjxwYXRoIHN0cm9rZT0iYmxhY2siIGZpbGw9Im5vbmUiIGQ9Ik05NC4yNiwtMjAuMTZDODEuODUsLTI4LjQzIDYzLjM3LC00MC43NSA0OC45MiwtNTAuMzgiIC8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiAvPgo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+ClkKWQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkFBLSZndDtZCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpaCloKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpBQS0mZ3Q7Wgo8cGF0aCBkPSJNMTM1LjQsLTE3LjA5QzE3OS4wOSwtMjYuOCAyNjQuNiwtNDUuOCAzMTMuNzgsLTU2LjczIiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpYLSZndDtCMQo8cGF0aCBkPSJNNDAuNzQsLTc2LjE2QzUzLjE1LC04NC40MyA3MS42MywtOTYuNzUgODYuMDgsLTEwNi4zOCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KWS0mZ3Q7QjEKPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE3NS4yNiwtNzYuMTZDMTYyLjg1LC04NC40MyAxNDQuMzcsLTk2Ljc1IDEyOS45MiwtMTA2LjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpaLSZndDtCMgo8cGF0aCBkPSJNMzUxLC03Ni40MUMzNTEsLTgzLjMgMzUxLC05Mi45IDM1MSwtMTAxLjQzIiBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==)
Figure [6](#fig:class.virtnonvirt) — Virtual and non-virtual base [[fig:class.virtnonvirt]](./fig:class.virtnonvirt)
— *end note*]
### [11.7.3](#class.virtual) Virtual functions [[class.virtual]](class.virtual)
[1](#class.virtual-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3830)
A non-static member function is a [*virtual function*](#def:function,virtual "11.7.3Virtual functions[class.virtual]") if it is first declared with the keyword virtual or
if it overrides a virtual member function declared in a base class
(see below)[.](#class.virtual-1.sentence-1)[92](#footnote-92 "The use of the virtual specifier in the declaration of an overriding function is valid but redundant (has empty semantics).")
[*Note [1](#class.virtual-note-1)*:
Virtual functions support dynamic binding and object-oriented
programming[.](#class.virtual-1.sentence-2)
— *end note*]
A class with a virtual member function is called a [*polymorphic class*](#def:class,polymorphic "11.7.3Virtual functions[class.virtual]")[.](#class.virtual-1.sentence-3)[93](#footnote-93 "If all virtual functions are immediate functions, the class is still polymorphic even if its internal representation does not otherwise require any additions for that polymorphic behavior.")
[2](#class.virtual-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3853)
If a virtual member function F is declared in a class B, and,
in a class D derived (directly or indirectly) from B,
a declaration of a member function G corresponds ([[basic.scope.scope]](basic.scope.scope "6.4.1General")) to a declaration of F,
ignoring trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")*s*,
then G [*overrides*](#def:function,virtual,override "11.7.3Virtual functions[class.virtual]")[94](#footnote-94 "A function with the same name but a different parameter list ([over]) as a virtual function is not necessarily virtual and does not override. Access control ([class.access]) is not considered in determining overriding.")F[.](#class.virtual-2.sentence-1)
For convenience, we say that any virtual function overrides itself[.](#class.virtual-2.sentence-2)
A virtual member function V of a class object S is a [*final
overrider*](#def:final_overrider "11.7.3Virtual functions[class.virtual]") unless the most derived class ([[intro.object]](intro.object "6.8.2Object model")) of which S is a
base class subobject (if any) has another member function that overrides V[.](#class.virtual-2.sentence-3)
In a derived class, if a virtual member function of a base class subobject
has more than one final overrider, the program is ill-formed[.](#class.virtual-2.sentence-4)
[*Example [1](#class.virtual-example-1)*: struct A {virtual void f();};struct B : virtual A {virtual void f();};struct C : B , virtual A {using A::f;};
void foo() { C c;
c.f(); // calls B::f, the final overrider c.C::f(); // calls A::f because of the using-declaration} — *end example*]
[*Example [2](#class.virtual-example-2)*: struct A { virtual void f(); };struct B : A { };struct C : A { void f(); };struct D : B, C { }; // OK, A::f and C::f are the final overriders// for the B and C subobjects, respectively — *end example*]
[3](#class.virtual-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3906)
[*Note [2](#class.virtual-note-2)*:
A virtual member function does not have to be visible to be overridden,
for example,struct B {virtual void f();};struct D : B {void f(int);};struct D2 : D {void f();}; the function f(int) in class D hides the virtual
function f() in its base class B; D::f(int) is
not a virtual function[.](#class.virtual-3.sentence-1)
However, f() declared in classD2 has the same name and the same parameter list asB::f(), and therefore is a virtual function that overrides the
function B::f() even though B::f() is not visible in
class D2[.](#class.virtual-3.sentence-2)
— *end note*]
[4](#class.virtual-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3930)
If a virtual function f in some class B is marked with the[*virt-specifier*](class.mem.general#nt:virt-specifier "11.4.1General[class.mem.general]") final and in a class D derived from B a function D::f overrides B::f, the program is ill-formed[.](#class.virtual-4.sentence-1)
[*Example [3](#class.virtual-example-3)*: struct B {virtual void f() const final;};
struct D : B {void f() const; // error: D::f attempts to override final B::f}; — *end example*]
[5](#class.virtual-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3946)
If a virtual function is marked with the [*virt-specifier*](class.mem.general#nt:virt-specifier "11.4.1General[class.mem.general]") override and
does not override a member function of a base class, the program is ill-formed[.](#class.virtual-5.sentence-1)
[*Example [4](#class.virtual-example-4)*: struct B {virtual void f(int);};
struct D : B {virtual void f(long) override; // error: wrong signature overriding B::fvirtual void f(int) override; // OK}; — *end example*]
[6](#class.virtual-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3962)
A virtual function shall not have a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[dcl.decl]](dcl.decl "9.3Declarators"))[.](#class.virtual-6.sentence-1)
[*Example [5](#class.virtual-example-5)*: template<typename T>struct A {virtual void f() requires true; // error: virtual function cannot be constrained ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))}; — *end example*]
[7](#class.virtual-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3973)
The [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]"), or lack thereof, of an overriding function
shall be the same as that of the overridden function[.](#class.virtual-7.sentence-1)
[8](#class.virtual-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3977)
The return type of an overriding function shall be either identical to
the return type of the overridden function or [*covariant*](#def:return_type,covariant "11.7.3Virtual functions[class.virtual]") with
the classes of the functions[.](#class.virtual-8.sentence-1)
If a function D::f overrides a
function B::f, the return types of the functions are covariant
if they satisfy the following criteria:
- [(8.1)](#class.virtual-8.1)
both are pointers to classes, both are lvalue references to
classes, or both are rvalue references to classes[95](#footnote-95 "Multi-level pointers to classes or references to multi-level pointers to classes are not allowed.")
- [(8.2)](#class.virtual-8.2)
the class in the return type of B::f is the same class as
the class in the return type of D::f, or is an unambiguous and
accessible direct or indirect base class of the class in the return type
of D::f
- [(8.3)](#class.virtual-8.3)
both pointers or references have the same cv-qualification and the
class type in the return type of D::f has the same
cv-qualification as or less cv-qualification than the class type in the
return type of B::f[.](#class.virtual-8.sentence-2)
[9](#class.virtual-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4002)
If the class type in the covariant return type of D::f differs from that ofB::f, the class type in the return type of D::f shall be
complete at the locus ([[basic.scope.pdecl]](basic.scope.pdecl "6.4.2Point of declaration")) of the overriding declaration or shall be the
class type D[.](#class.virtual-9.sentence-1)
When the overriding function is called as the
final overrider of the overridden function, its result is converted to
the type returned by the (statically chosen) overridden
function ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#class.virtual-9.sentence-2)
[*Example [6](#class.virtual-example-6)*: class B { };class D : private B { friend class Derived; };struct Base {virtual void vf1(); virtual void vf2(); virtual void vf3(); virtual B* vf4(); virtual B* vf5(); void f();};
struct No_good : public Base { D* vf4(); // error: B (base class of D) inaccessible};
class A;struct Derived : public Base {void vf1(); // virtual and overrides Base::vf1()void vf2(int); // not virtual, hides Base::vf2()char vf3(); // error: invalid difference in return type only D* vf4(); // OK, returns pointer to derived class A* vf5(); // error: returns pointer to incomplete classvoid f();};
void g() { Derived d;
Base* bp = &d; // standard conversion:// Derived* to Base* bp->vf1(); // calls Derived::vf1() bp->vf2(); // calls Base::vf2() bp->f(); // calls Base::f() (not virtual) B* p = bp->vf4(); // calls Derived::vf4() and converts the// result to B* Derived* dp = &d;
D* q = dp->vf4(); // calls Derived::vf4() and does not// convert the result to B* dp->vf2(); // error: argument mismatch} — *end example*]
[10](#class.virtual-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4054)
[*Note [3](#class.virtual-note-3)*:
The interpretation of the call of a virtual function depends on the type
of the object for which it is called (the dynamic type), whereas the
interpretation of a call of a non-virtual member function depends only
on the type of the pointer or reference denoting that object (the static
type) ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#class.virtual-10.sentence-1)
— *end note*]
[11](#class.virtual-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4063)
[*Note [4](#class.virtual-note-4)*:
The virtual specifier implies membership, so a virtual function
cannot be a non-member ([[dcl.fct.spec]](dcl.fct.spec "9.2.3Function specifiers")) function[.](#class.virtual-11.sentence-1)
Nor can a virtual
function be a static member, since a virtual function call relies on a
specific object for determining which function to invoke[.](#class.virtual-11.sentence-2)
A virtual
function declared in one class can be declared a friend ([[class.friend]](class.friend "11.8.4Friends")) in
another class[.](#class.virtual-11.sentence-3)
— *end note*]
[12](#class.virtual-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4073)
A virtual function declared in a class shall be defined, or declared
pure ([[class.abstract]](#class.abstract "11.7.4Abstract classes")) in that class, or both; no diagnostic is
required ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))[.](#class.virtual-12.sentence-1)
[13](#class.virtual-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4080)
[*Example [7](#class.virtual-example-7)*:
Here are some uses of virtual functions with multiple base classes:struct A {virtual void f();};
struct B1 : A { // note non-virtual derivationvoid f();};
struct B2 : A {void f();};
struct D : B1, B2 { // D has two separate A subobjects};
void foo() { D d;// A* ap = &d; // would be ill-formed: ambiguous B1* b1p = &d;
A* ap = b1p;
D* dp = &d;
ap->f(); // calls D::B1::f dp->f(); // error: ambiguous}
In class D above there are two occurrences of class A and hence two occurrences of the virtual member function A::f[.](#class.virtual-13.sentence-2)
The final overrider of B1::A::f is B1::f and the final
overrider of B2::A::f is B2::f[.](#class.virtual-13.sentence-3)
— *end example*]
[14](#class.virtual-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4116)
[*Example [8](#class.virtual-example-8)*:
The following example shows a function that does not have a unique final
overrider:struct A {virtual void f();};
struct VB1 : virtual A { // note virtual derivationvoid f();};
struct VB2 : virtual A {void f();};
struct Error : VB1, VB2 { // error};
struct Okay : VB1, VB2 {void f();};
Both VB1::f and VB2::f override A::f but there
is no overrider of both of them in class Error[.](#class.virtual-14.sentence-2)
This example is
therefore ill-formed[.](#class.virtual-14.sentence-3)
Class Okay is well-formed, however,
because Okay::f is a final overrider[.](#class.virtual-14.sentence-4)
— *end example*]
[15](#class.virtual-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4146)
[*Example [9](#class.virtual-example-9)*:
The following example uses the well-formed classes from above[.](#class.virtual-15.sentence-1)
struct VB1a : virtual A { // does not declare f};
struct Da : VB1a, VB2 {};
void foe() { VB1a* vb1ap = new Da;
vb1ap->f(); // calls VB2::f} — *end example*]
[16](#class.virtual-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4163)
Explicit qualification with the scope operator ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names"))
suppresses the virtual call mechanism[.](#class.virtual-16.sentence-1)
[*Example [10](#class.virtual-example-10)*: class B { public: virtual void f(); };class D : public B { public: void f(); };
void D::f() { /* ... */ B::f(); }
Here, the function call inD::f really does callB::f and notD::f[.](#class.virtual-16.sentence-2)
— *end example*]
[17](#class.virtual-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4184)
A deleted function ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions")) shall
not override a function that is not deleted[.](#class.virtual-17.sentence-1)
Likewise,
a function that is not deleted shall not override a
deleted function[.](#class.virtual-17.sentence-2)
[18](#class.virtual-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4191)
A consteval virtual function shall not override
a virtual function that is not consteval[.](#class.virtual-18.sentence-1)
A consteval virtual function shall not be overridden by
a virtual function that is not consteval[.](#class.virtual-18.sentence-2)
[92)](#footnote-92)[92)](#footnoteref-92)
The use of the virtual specifier in the
declaration of an overriding function is valid but redundant (has empty
semantics)[.](#footnote-92.sentence-1)
[93)](#footnote-93)[93)](#footnoteref-93)
If
all virtual functions are immediate functions,
the class is still polymorphic even if
its internal representation does not otherwise require
any additions for that polymorphic behavior[.](#footnote-93.sentence-1)
[94)](#footnote-94)[94)](#footnoteref-94)
A function
with the same name but a different parameter list ([[over]](over "12Overloading"))
as a virtual function is not necessarily virtual and
does not override[.](#footnote-94.sentence-1)
Access control ([[class.access]](class.access "11.8Member access control")) is not considered in
determining overriding[.](#footnote-94.sentence-2)
[95)](#footnote-95)[95)](#footnoteref-95)
Multi-level pointers to classes or references to multi-level pointers to
classes are not allowed[.](#footnote-95.sentence-1)
### [11.7.4](#class.abstract) Abstract classes [[class.abstract]](class.abstract)
[1](#class.abstract-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4199)
[*Note [1](#class.abstract-note-1)*:
The abstract class mechanism supports the notion of a general concept,
such as a shape, of which only more concrete variants, such ascircle and square, can actually be used[.](#class.abstract-1.sentence-1)
An abstract
class can also be used to define an interface for which derived classes
provide a variety of implementations[.](#class.abstract-1.sentence-2)
— *end note*]
[2](#class.abstract-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4208)
A virtual function is specified as
a [*pure virtual function*](#def:function,virtual,pure "11.7.4Abstract classes[class.abstract]") by using a[*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1General[class.mem.general]") ([[class.mem]](class.mem "11.4Class members")) in the function declaration
in the class definition[.](#class.abstract-2.sentence-1)
[*Note [2](#class.abstract-note-2)*:
Such a function might be inherited: see below[.](#class.abstract-2.sentence-2)
— *end note*]
A class is an [*abstract class*](#def:class,abstract "11.7.4Abstract classes[class.abstract]") if it has at least one pure virtual function[.](#class.abstract-2.sentence-3)
[*Note [3](#class.abstract-note-3)*:
An abstract class can be used only as a base class of some other class;
no objects of an abstract class can be created
except as subobjects of a class
derived from it ([[basic.def]](basic.def "6.2Declarations and definitions"), [[class.mem]](class.mem "11.4Class members"))[.](#class.abstract-2.sentence-4)
— *end note*]
A pure virtual function need be defined only if called with, or as if
with ([[class.dtor]](class.dtor "11.4.7Destructors")), the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") syntax ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names"))[.](#class.abstract-2.sentence-5)
[*Example [1](#class.abstract-example-1)*: class point { /* ... */ };class shape { // abstract class point center;public: point where() { return center; }void move(point p) { center=p; draw(); }virtual void rotate(int) = 0; // pure virtualvirtual void draw() = 0; // pure virtual}; — *end example*]
[*Note [4](#class.abstract-note-4)*:
A function declaration cannot provide both a [*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1General[class.mem.general]") and a definition[.](#class.abstract-2.sentence-6)
— *end note*]
[*Example [2](#class.abstract-example-2)*: struct C {virtual void f() = 0 { }; // error}; — *end example*]
[3](#class.abstract-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4253)
[*Note [5](#class.abstract-note-5)*:
An abstract class type cannot be used
as a parameter or return type of
a function being defined ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) or called ([[expr.call]](expr.call "7.6.1.3Function call")),
except as specified in [[dcl.type.simple]](dcl.type.simple "9.2.9.3Simple type specifiers")[.](#class.abstract-3.sentence-1)
Further, an abstract class type cannot be used as
the type of an explicit type conversion ([[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10Reinterpret cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11Const cast")),
because the resulting prvalue would be of abstract class type ([[basic.lval]](basic.lval "7.2.1Value category"))[.](#class.abstract-3.sentence-2)
However, pointers and references to abstract class types
can appear in such contexts[.](#class.abstract-3.sentence-3)
— *end note*]
[4](#class.abstract-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4267)
A class is abstract if it has at least one pure virtual
function for which the final overrider is pure virtual[.](#class.abstract-4.sentence-1)
[*Example [3](#class.abstract-example-3)*: class ab_circle : public shape {int radius;public:void rotate(int) { }// ab_circle::draw() is a pure virtual};
Since shape::draw() is a pure virtual functionab_circle::draw() is a pure virtual by default[.](#class.abstract-4.sentence-2)
The alternative
declaration,class circle : public shape {int radius;public:void rotate(int) { }void draw(); // a definition is required somewhere}; would make class circle non-abstract and a definition ofcircle::draw() must be provided[.](#class.abstract-4.sentence-3)
— *end example*]
[5](#class.abstract-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4296)
[*Note [6](#class.abstract-note-6)*:
An abstract class can be derived from a class that is not abstract, and
a pure virtual function can override a virtual function which is not
pure[.](#class.abstract-5.sentence-1)
— *end note*]
[6](#class.abstract-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4303)
Member functions can be called from a constructor (or destructor) of an
abstract class;the effect of making a virtual call ([[class.virtual]](#class.virtual "11.7.3Virtual functions")) to a pure
virtual function directly or indirectly for the object being created (or
destroyed) from such a constructor (or destructor) is undefined[.](#class.abstract-6.sentence-1)

View File

@@ -0,0 +1,179 @@
[class.derived.general]
# 11 Classes [[class]](./#class)
## 11.7 Derived classes [[class.derived]](class.derived#general)
### 11.7.1 General [class.derived.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3511)
A list of base classes can be specified in a class definition using
the notation:
[base-clause:](#nt:base-clause "11.7.1General[class.derived.general]")
: [*base-specifier-list*](#nt:base-specifier-list "11.7.1General[class.derived.general]")
[base-specifier-list:](#nt:base-specifier-list "11.7.1General[class.derived.general]")
[*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") ...opt
[*base-specifier-list*](#nt:base-specifier-list "11.7.1General[class.derived.general]") , [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") ...opt
[base-specifier:](#nt:base-specifier "11.7.1General[class.derived.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt virtual [*access-specifier*](#nt:access-specifier "11.7.1General[class.derived.general]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*access-specifier*](#nt:access-specifier "11.7.1General[class.derived.general]") virtualopt [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[class-or-decltype:](#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") template [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")
[access-specifier:](#nt:access-specifier "11.7.1General[class.derived.general]")
private
protected
public
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]")[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3554)
The component names of a [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]") are those of its[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"),[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]"), and/or[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")[.](#2.sentence-1)
A [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]") shall denote
a (possibly cv-qualified) class type that is not
an incompletely defined class ([[class.mem]](class.mem "11.4Class members"));
any cv-qualifiers are ignored[.](#2.sentence-2)
The class denoted by the [*class-or-decltype*](#nt:class-or-decltype "11.7.1General[class.derived.general]") of
a [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") is called a[*direct base class*](#def:base_class,direct "11.7.1General[class.derived.general]") for the class being defined;
for each such [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]"),
the corresponding [*direct base class relationship*](#def:relationship,direct_base_class "11.7.1General[class.derived.general]") is the ordered pair (D, B)
where D is the class being defined andB is the direct base class[.](#2.sentence-3)
The lookup for the component name of
the [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") is type-only ([[basic.lookup]](basic.lookup "6.5Name lookup"))[.](#2.sentence-4)
A class B is a
base class of a class D if it is a direct base class ofD or a direct base class of one of D's base classes[.](#2.sentence-5)
A class is an [*indirect base class*](#def:base_class,indirect "11.7.1General[class.derived.general]") of another if it is a base
class but not a direct base class[.](#2.sentence-6)
A class is said to be (directly or
indirectly) [*derived*](#def:derived) from its (direct or indirect) base
classes[.](#2.sentence-7)
[*Note [1](#note-1)*:
See [[class.access]](class.access "11.8Member access control") for the meaning of[*access-specifier*](#nt:access-specifier "11.7.1General[class.derived.general]")[.](#2.sentence-8)
— *end note*]
Members of a base class are also members of the derived class[.](#2.sentence-9)
[*Note [2](#note-2)*:
Constructors of a base class can be explicitly inherited ([[namespace.udecl]](namespace.udecl "9.10The using declaration"))[.](#2.sentence-10)
Base class members can be referred to in
expressions in the same manner as other members of the derived class,
unless their names are hidden or ambiguous ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))[.](#2.sentence-11)
The scope resolution operator :: ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names")) can be used
to refer to a direct or indirect base member explicitly,
even if it is hidden in the derived class[.](#2.sentence-12)
A derived class can itself serve as a base class subject to access
control; see [[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members")[.](#2.sentence-13)
A pointer to a derived class can be
implicitly converted to a pointer to an accessible unambiguous base
class ([[conv.ptr]](conv.ptr "7.3.12Pointer conversions"))[.](#2.sentence-14)
An lvalue of a derived class type can be bound
to a reference to an accessible unambiguous base
class ([[dcl.init.ref]](dcl.init.ref "9.5.4References"))[.](#2.sentence-15)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3609)
The [*base-specifier-list*](#nt:base-specifier-list "11.7.1General[class.derived.general]") specifies the type of the[*base class subobjects*](#def:base_class_subobjects) contained in an
object of the derived class type[.](#3.sentence-1)
[*Example [1](#example-1)*: struct Base {int a, b, c;};
struct Derived : Base {int b;};
struct Derived2 : Derived {int c;};
Here, an object of class Derived2 will have a subobject of classDerived which in turn will have a subobject of classBase[.](#3.sentence-2)
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3637)
A [*base-specifier*](#nt:base-specifier "11.7.1General[class.derived.general]") followed by an ellipsis is a pack
expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates"))[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3641)
The order in which the base class subobjects are allocated in the most
derived object ([[intro.object]](intro.object "6.8.2Object model")) is unspecified[.](#5.sentence-1)
[*Note [3](#note-3)*:
A derived class and its base class subobjects can be represented by a
directed acyclic graph (DAG) where an arrow means “directly derived
from” (see Figure [3](#fig:class.dag))[.](#5.sentence-2)
An arrow need not have a physical representation in memory[.](#5.sentence-3)
A DAG of subobjects is often referred to as a “subobject lattice”[.](#5.sentence-4)
— *end note*]
![SVG Image](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNzlwdCIgdmlld0JveD0iMC4wMCAwLjAwIDc5LjAwIDE0MC4wMCIgaGVpZ2h0PSIxNDBwdCI+CjxnIGNsYXNzPSJncmFwaCI+CmRhZwoKPGcgY2xhc3M9Im5vZGUiPgpCYXNlCkJhc2UKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpEZXJpdmVkMQpEZXJpdmVkMQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkRlcml2ZWQxLSZndDtCYXNlCjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0zNS41LC03Ni40MUMzNS41LC04My4zIDM1LjUsLTkyLjkgMzUuNSwtMTAxLjQzIiBzdHJva2U9ImJsYWNrIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpEZXJpdmVkMgpEZXJpdmVkMgo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkRlcml2ZWQyLSZndDtEZXJpdmVkMQo8cGF0aCBzdHJva2U9ImJsYWNrIiBkPSJNMzUuNSwtMjAuNDFDMzUuNSwtMjcuMyAzNS41LC0zNi45IDM1LjUsLTQ1LjQzIiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==)
Figure [3](#fig:class.dag) — Directed acyclic graph [[fig:class.dag]](./fig:class.dag)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3661)
[*Note [4](#note-4)*:
Initialization of objects representing base classes can be specified in
constructors; see [[class.base.init]](class.base.init "11.9.3Initializing bases and members")[.](#6.sentence-1)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3667)
[*Note [5](#note-5)*:
A base class subobject can have a layout different
from the layout of a most derived object of the same type[.](#7.sentence-1)
A base class
subobject can have a polymorphic behavior ([[class.cdtor]](class.cdtor "11.9.5Construction and destruction"))
different from the polymorphic behavior of a most derived object of the
same type[.](#7.sentence-2)
A base class subobject can be of zero size;
however, two subobjects that have the same class type and that belong to
the same most derived object cannot be allocated at the same
address ([[intro.object]](intro.object "6.8.2Object model"))[.](#7.sentence-3)
— *end note*]

389
cppdraft/class/dtor.md Normal file
View File

@@ -0,0 +1,389 @@
[class.dtor]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.dtor)
### 11.4.7 Destructors [class.dtor]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2082)
A declaration whose [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") has an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2Unqualified names[expr.prim.id.unqual]") that begins with a ~ declares a [*prospective destructor*](#def:destructor,prospective "11.4.7Destructors[class.dtor]");
its [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") shall be a function declarator ([[dcl.fct]](dcl.fct "9.3.4.6Functions")) of the form
[*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1General[dcl.decl.general]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") ) [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt
where the [*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1General[dcl.decl.general]") consists solely of an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]"), an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"),
and optional surrounding parentheses, and the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") has
one of the following forms:
- [(1.1)](#1.1)
in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") that belongs to the[*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of a class or class template
but is not a friend
declaration ([[class.friend]](class.friend "11.8.4Friends")), the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is~[*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]") and the [*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]") is the
injected-class-name ([[class.pre]](class.pre "11.1Preamble")) of the immediately-enclosing entity or
- [(1.2)](#1.2)
otherwise, the[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1General[expr.prim.id.general]") is [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")~[*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]") and the [*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]") is the injected-class-name of the
class nominated by the [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")[.](#1.sentence-1)
A prospective destructor shall take no arguments ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#1.sentence-2)
Each [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1General[dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a prospective destructor declaration (if any)
shall befriend,inline,virtual, orconstexpr[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2120)
If a class has no user-declared
prospective destructor,
a prospective destructor is implicitly
declared as defaulted ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions"))[.](#2.sentence-1)
An implicitly-declared prospective destructor is an
inline public member of its class[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2130)
An implicitly-declared prospective destructor for a class X will have the form~X()
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2136)
At the end of the definition of a class,
overload resolution is performed
among the prospective destructors declared in that class
with an empty argument list
to select the [*destructor*](#def:destructor "11.4.7Destructors[class.dtor]") for the class,
also known as the [*selected destructor*](#def:destructor,selected "11.4.7Destructors[class.dtor]")[.](#4.sentence-1)
The program is ill-formed if overload resolution fails[.](#4.sentence-2)
Destructor selection does not constitute
a reference to,
or odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) of,
the selected destructor,
and in particular,
the selected destructor may be deleted ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3Deleted definitions"))[.](#4.sentence-3)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2151)
The address of a destructor shall not be taken[.](#5.sentence-1)
[*Note [1](#note-1)*:
A return statement in the body of a destructor
cannot specify a return value ([[stmt.return]](stmt.return "8.8.4The return statement"))[.](#5.sentence-2)
— *end note*]
A destructor can be invoked for aconst,volatile orconstvolatile object[.](#5.sentence-3)
const andvolatile semantics ([[dcl.type.cv]](dcl.type.cv "9.2.9.2The cv-qualifiers")) are not applied on an object under destruction[.](#5.sentence-4)
They stop being in effect when the destructor for the
most derived object ([[intro.object]](intro.object "6.8.2Object model")) starts[.](#5.sentence-5)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2175)
[*Note [2](#note-2)*:
A declaration of a destructor that does not have a [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") has the same exception specification as if it had been implicitly declared ([[except.spec]](except.spec "14.5Exception specifications"))[.](#6.sentence-1)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2181)
A defaulted destructor for a class X is defined as deleted if
- [(7.1)](#7.1)
X is a non-union class and
any non-variant potentially constructed subobject has class type M (or possibly multidimensional array thereof) where M has a destructor that is deleted or
is inaccessible from the defaulted destructor,
- [(7.2)](#7.2)
X is a union and
* [(7.2.1)](#7.2.1)
overload resolution to select a constructor to
default-initialize an object of type X either fails or
selects a constructor that is either deleted or not trivial, or
* [(7.2.2)](#7.2.2)
X has a variant member V of
class type M (or possibly multi-dimensional array thereof)
where V has a default member initializer and M has a destructor that is non-trivial, or,
- [(7.3)](#7.3)
for a virtual destructor, lookup of the non-array deallocation
function results in an ambiguity or in a function that is deleted or
inaccessible from the defaulted destructor[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2210)
A destructor for a class X is trivial if it is not user-provided and if
- [(8.1)](#8.1)
the destructor is not virtual,
- [(8.2)](#8.2)
all of the direct base classes of X have trivial destructors, and
- [(8.3)](#8.3)
either X is a union or
for all of the non-variant non-static data members of X that are of class
type (or array thereof), each such class has a trivial destructor[.](#8.sentence-1)
Otherwise, the destructor is[*non-trivial*](#def:destructor,non-trivial "11.4.7Destructors[class.dtor]")[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2225)
A defaulted destructor is a constexpr destructor
if it is constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers"))[.](#9.sentence-1)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2229)
Before a
defaulted destructor for a class is implicitly defined, all the non-user-provided
destructors for its base classes and its non-static data members are
implicitly defined[.](#10.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2235)
A prospective destructor can be
declared virtual ([[class.virtual]](class.virtual "11.7.3Virtual functions"))
and with a [*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1General[class.mem.general]") ([[class.abstract]](class.abstract "11.7.4Abstract classes"))[.](#11.sentence-1)
If the destructor of a class is virtual and
any objects of that class or any derived class are created in the program,
the destructor shall be defined[.](#11.sentence-2)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2245)
[*Note [3](#note-3)*:
Some language constructs have special semantics when used during destruction;
see [[class.cdtor]](class.cdtor "11.9.5Construction and destruction")[.](#12.sentence-1)
— *end note*]
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2252)
After executing the body of the destructor and destroying
any objects with automatic storage duration allocated within the body, a
destructor for classX calls the destructors forX's
direct non-variant non-static data members other than anonymous unions,
the destructors forX's
non-virtual direct base classes and, ifX is the most derived class ([[class.base.init]](class.base.init "11.9.3Initializing bases and members")),
its destructor calls the destructors forX's
virtual base classes[.](#13.sentence-1)
All destructors are called as if they were referenced with a qualified name,
that is, ignoring any possible virtual overriding destructors in more
derived classes[.](#13.sentence-2)
Bases and members are destroyed in the reverse order of the completion of
their constructor (see [[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#13.sentence-3)
[*Note [4](#note-4)*:
Areturn statement ([[stmt.return]](stmt.return "8.8.4The return statement")) in a destructor might not directly return to the
caller; before transferring control to the caller, the destructors for the
members and bases are called[.](#13.sentence-4)
— *end note*]
Destructors for elements of an array are called in reverse order of their
construction (see [[class.init]](class.init "11.9Initialization"))[.](#13.sentence-5)
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2287)
A destructor is invoked implicitly
- [(14.1)](#14.1)
for a constructed object with static storage duration ([[basic.stc.static]](basic.stc.static "6.8.6.2Static storage duration")) at program termination ([[basic.start.term]](basic.start.term "6.10.3.4Termination")),
- [(14.2)](#14.2)
for a constructed object with thread storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3Thread storage duration")) at thread exit,
- [(14.3)](#14.3)
for a constructed object with automatic storage duration ([[basic.stc.auto]](basic.stc.auto "6.8.6.4Automatic storage duration")) when the block in which an object is created exits ([[stmt.dcl]](stmt.dcl "8.10Declaration statement")),
- [(14.4)](#14.4)
for a constructed temporary object when its lifetime ends ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion"), [[class.temporary]](class.temporary "6.8.7Temporary objects"))[.](#14.sentence-1)
In each case, the context of the invocation is the context of the construction of
the object[.](#14.sentence-2)
A destructor may also be invoked implicitly through use of a[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9Delete[expr.delete]") ([[expr.delete]](expr.delete "7.6.2.9Delete")) for a constructed object allocated
by a [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New")); the context of the invocation is the[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9Delete[expr.delete]")[.](#14.sentence-3)
[*Note [5](#note-5)*:
An array of class type contains several subobjects for each of which
the destructor is invoked[.](#14.sentence-4)
— *end note*]
A destructor can also be invoked explicitly[.](#14.sentence-5)
A destructor is [*potentially invoked*](#def:potentially_invoked "11.4.7Destructors[class.dtor]") if it is invoked or as specified in [[expr.new]](expr.new "7.6.2.8New"),[[stmt.return]](stmt.return "8.8.4The return statement"), [[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"),[[class.base.init]](class.base.init "11.9.3Initializing bases and members"), and [[except.throw]](except.throw "14.2Throwing an exception")[.](#14.sentence-6)
A program is ill-formed if a destructor that is potentially invoked is deleted
or not accessible from the context of the invocation[.](#14.sentence-7)
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2319)
At the point of definition of a virtual destructor (including an implicit
definition), the non-array deallocation function is
determined as if for the expression delete this appearing in a
non-virtual destructor of the destructor's class (see [[expr.delete]](expr.delete "7.6.2.9Delete"))[.](#15.sentence-1)
If the lookup fails or if the deallocation function has
a deleted definition ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions")), the program is ill-formed[.](#15.sentence-2)
[*Note [6](#note-6)*:
This assures that a deallocation function corresponding to the dynamic type of an
object is available for the[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9Delete[expr.delete]") ([[class.free]](class.free "11.4.11Allocation and deallocation functions"))[.](#15.sentence-3)
— *end note*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2332)
In an explicit destructor call, the destructor is specified by a~ followed by a[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3Simple type specifiers[dcl.type.simple]") or [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]") that denotes the destructor's class type[.](#16.sentence-1)
The invocation of a destructor is subject to the usual rules for member
functions ([[class.mfct]](class.mfct "11.4.2Member functions"));
that is, if the object is not of the destructor's class type and
not of a class derived from the destructor's class type (including when
the destructor is invoked via a null pointer value), the program has
undefined behavior[.](#16.sentence-2)
[*Note [7](#note-7)*:
Invoking delete on a null pointer does not call the
destructor; see [[expr.delete]](expr.delete "7.6.2.9Delete")[.](#16.sentence-3)
— *end note*]
[*Example [1](#example-1)*: struct B {virtual ~B() { }};struct D : B {~D() { }};
D D_object;typedef B B_alias;
B* B_ptr = &D_object;
void f() { D_object.B::~B(); // calls B's destructor B_ptr->~B(); // calls D's destructor B_ptr->~B_alias(); // calls D's destructor B_ptr->B_alias::~B(); // calls B's destructor B_ptr->B_alias::~B_alias(); // calls B's destructor} — *end example*]
[*Note [8](#note-8)*:
An explicit destructor call must always be written using
a member access operator ([[expr.ref]](expr.ref "7.6.1.5Class member access")) or a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names"));
in particular, the[*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1General[expr.unary.general]")~X() in a member function is not an explicit destructor call ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators"))[.](#16.sentence-4)
— *end note*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2380)
[*Note [9](#note-9)*:
Explicit calls of destructors are rarely needed[.](#17.sentence-1)
One use of such calls is for objects placed at specific
addresses using a placement[*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]")[.](#17.sentence-2)
Such use of explicit placement and destruction of objects can be necessary
to cope with dedicated hardware resources and for writing memory management
facilities[.](#17.sentence-3)
[*Example [2](#example-2)*: void* operator new(std::size_t, void* p) { return p; }struct X { X(int); ~X();};void f(X* p);
void g() { // rare, specialized use:char* buf = new char[sizeof(X)];
X* p = new(buf) X(222); // use buf[] and initialize f(p);
p->X::~X(); // cleanup} — *end example*]
— *end note*]
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2409)
Once a destructor is invoked for an object, the object's lifetime ends;
the behavior is undefined if the destructor is invoked
for an object whose lifetime has ended ([[basic.life]](basic.life "6.8.4Lifetime"))[.](#18.sentence-1)
[*Example [3](#example-3)*:
If the destructor for an object with automatic storage duration is explicitly invoked,
and the block is subsequently left in a manner that would ordinarily
invoke implicit destruction of the object, the behavior is undefined[.](#18.sentence-2)
— *end example*]
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2419)
[*Note [10](#note-10)*:
The notation for explicit call of a destructor can be used for any scalar type
name ([[expr.prim.id.dtor]](expr.prim.id.dtor "7.5.5.5Destruction"))[.](#19.sentence-1)
Allowing this makes it possible to write code without having to know if a
destructor exists for a given type[.](#19.sentence-2)
For example:typedef int I;
I* p;
p->I::~I();
— *end note*]
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2434)
A destructor shall not be a coroutine[.](#20.sentence-1)

41
cppdraft/class/eq.md Normal file
View File

@@ -0,0 +1,41 @@
[class.eq]
# 11 Classes [[class]](./#class)
## 11.10 Comparisons [[class.compare]](class.compare#class.eq)
### 11.10.2 Equality operator [class.eq]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6693)
A defaulted equality operator function ([[over.binary]](over.binary "12.4.3Binary operators"))
shall have a declared return type bool[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6697)
A defaulted == operator function for a class C is defined as deleted
unless, for each xi in the expanded list of subobjects
for an object x of type C,xi == xi is usable ([[class.compare.default]](class.compare.default "11.10.1Defaulted comparison operator functions"))[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6705)
The return value of a defaulted == operator function
with parameters x and y is determined
by comparing corresponding elements xi and yi in the expanded lists of subobjects for x and y (in increasing index order)
until the first index i where xi == yi yields a result value which,
when contextually converted to bool, yields false[.](#3.sentence-1)
The return value is false if such an index exists
and true otherwise[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6717)
[*Example [1](#example-1)*: struct D {int i; friend bool operator==(const D& x, const D& y) = default; // OK, returns x.i == y.i}; — *end example*]

View File

@@ -0,0 +1,87 @@
[class.expl.init]
# 11 Classes [[class]](./#class)
## 11.9 Initialization [[class.init]](class.init#class.expl.init)
### 11.9.2 Explicit initialization [class.expl.init]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5369)
An object of class type can be initialized with a parenthesized[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]"),
where the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") is construed as an argument list for a constructor
that is called to initialize the object[.](#1.sentence-1)
Alternatively, a single[*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") can be specified as an[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") using the= form of initialization[.](#1.sentence-2)
Either direct-initialization semantics or copy-initialization semantics apply;
see [[dcl.init]](dcl.init "9.5Initializers")[.](#1.sentence-3)
[*Example [1](#example-1)*: struct complex { complex();
complex(double);
complex(double,double);};
complex sqrt(complex,complex);
complex a(1); // initialized by calling complex(double) with argument 1 complex b = a; // initialized as a copy of a complex c = complex(1,2); // initialized by calling complex(double,double) with arguments 1 and 2 complex d = sqrt(b,c); // initialized by calling sqrt(complex,complex) with d as its result object complex e; // initialized by calling complex() complex f = 3; // initialized by calling complex(double) with argument 3 complex g = { 1, 2 }; // initialized by calling complex(double, double) with arguments 1 and 2 — *end example*]
[*Note [1](#note-1)*:
Overloading of the assignment operator ([[over.assign]](over.assign "12.4.3.2Simple assignment"))
has no effect on initialization[.](#1.sentence-4)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5410)
An object of class type can also be initialized by a[*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")[.](#2.sentence-1)
List-initialization semantics apply;
see [[dcl.init]](dcl.init "9.5Initializers") and [[dcl.init.list]](dcl.init.list "9.5.5List-initialization")[.](#2.sentence-2)
[*Example [2](#example-2)*: complex v[6] = { 1, complex(1,2), complex(), 2 };
Here,complex::complex(double) is called for the initialization ofv[0] andv[3],complex::complex(double, double) is called for the initialization ofv[1],complex::complex() is called for the initialization ofv[2],v[4],
andv[5][.](#2.sentence-3)
For another example,
struct X {int i; float f;
complex c;} x = { 99, 88.8, 77.7 };
Here,x.i is initialized with 99,x.f is initialized with 88.8, andcomplex::complex(double) is called for the initialization ofx.c[.](#2.sentence-5)
— *end example*]
[*Note [2](#note-2)*:
Braces can be elided in the[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") for any aggregate, even if the aggregate has members of a class type with
user-defined type conversions; see [[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates")[.](#2.sentence-6)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5462)
[*Note [3](#note-3)*:
IfT is a class type with no default constructor,
any initializing declaration of an object of typeT (or array thereof) is ill-formed if no[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") is explicitly specified (see [[class.init]](class.init "11.9Initialization") and [[dcl.init]](dcl.init "9.5Initializers"))[.](#3.sentence-1)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5474)
[*Note [4](#note-4)*:
The order in which objects with static or thread storage duration
are initialized is described in [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3Dynamic initialization of non-block variables") and [[stmt.dcl]](stmt.dcl "8.10Declaration statement")[.](#4.sentence-1)
— *end note*]

101
cppdraft/class/free.md Normal file
View File

@@ -0,0 +1,101 @@
[class.free]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.free)
### 11.4.11 Allocation and deallocation functions [class.free]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2966)
Any allocation function for a classT is a static member (even if not explicitly declaredstatic)[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2974)
[*Example [1](#example-1)*: class Arena;struct B {void* operator new(std::size_t, Arena*);};struct D1 : B {};
Arena* ap;void foo(int i) {new (ap) D1; // calls B::operator new(std::size_t, Arena*)new D1[i]; // calls ::operator new[](std::size_t)new D1; // error: ::operator new(std::size_t) hidden} — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2993)
Any deallocation function for a classX is a static member (even if not explicitly declaredstatic)[.](#3.sentence-1)
[*Example [2](#example-2)*: class X {void operator delete(void*); void operator delete[](void*, std::size_t);};
class Y {void operator delete(void*, std::size_t); void operator delete[](void*);}; — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3014)
Since member allocation and deallocation functions arestatic they cannot be virtual[.](#4.sentence-1)
[*Note [1](#note-1)*:
However, when the[*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") of a[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9Delete[expr.delete]") refers to an object of class type with a virtual destructor,
because the deallocation function is chosen by the destructor
of the dynamic type of the object, the effect is the same in that case[.](#4.sentence-2)
[*Example [3](#example-3)*: struct B {virtual ~B(); void operator delete(void*, std::size_t);};
struct D : B {void operator delete(void*);};
struct E : B {void log_deletion(); void operator delete(E *p, std::destroying_delete_t) { p->log_deletion();
p->~E(); ::operator delete(p); }};
void f() { B* bp = new D; delete bp; // 1: uses D::operator delete(void*) bp = new E; delete bp; // 2: uses E::operator delete(E*, std::destroying_delete_t)}
Here, storage for the object of classD is deallocated byD::operator delete(),
and
the object of class E is destroyed
and its storage is deallocated
by E::operator delete(),
due to the virtual destructor[.](#4.sentence-3)
— *end example*]
— *end note*]
[*Note [2](#note-2)*:
Virtual destructors have no effect on the deallocation function actually
called when the[*cast-expression*](expr.cast#nt:cast-expression "7.6.3Explicit type conversion (cast notation)[expr.cast]") of a[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9Delete[expr.delete]") refers to an array of objects of class type[.](#4.sentence-4)
[*Example [4](#example-4)*: struct B {virtual ~B(); void operator delete[](void*, std::size_t);};
struct D : B {void operator delete[](void*, std::size_t);};
void f(int i) { D* dp = new D[i]; delete [] dp; // uses D::operator delete[](void*, std::size_t) B* bp = new D[i]; delete[] bp; // undefined behavior} — *end example*]
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3092)
Access to the deallocation function is checked statically,
even if a different one is actually executed[.](#5.sentence-1)
[*Example [5](#example-5)*:
For the call on line “// 1” above,
ifB::operator delete() had been private, the delete expression would have been ill-formed[.](#5.sentence-2)
— *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3102)
[*Note [3](#note-3)*:
If a deallocation function has no explicit [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]"), it
has a non-throwing exception specification ([[except.spec]](except.spec "14.5Exception specifications"))[.](#6.sentence-1)
— *end note*]

167
cppdraft/class/friend.md Normal file
View File

@@ -0,0 +1,167 @@
[class.friend]
# 11 Classes [[class]](./#class)
## 11.8 Member access control [[class.access]](class.access#class.friend)
### 11.8.4 Friends [class.friend]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4916)
A friend of a class is a function or class that is
given permission to name the private and protected members of the class[.](#1.sentence-1)
A class specifies its friends, if any, by way of friend declarations[.](#1.sentence-2)
Such declarations give special access rights to the friends, but they
do not make the nominated friends members of the befriending class[.](#1.sentence-3)
[*Example [1](#example-1)*:
The following example illustrates the differences between
members and friends:class X {int a; friend void friend_set(X*, int);public:void member_set(int);};
void friend_set(X* p, int i) { p->a = i; }void X::member_set(int i) { a = i; }void f() { X obj;
friend_set(&obj,10);
obj.member_set(10);}
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4946)
Declaring a class to be a friend implies that private and
protected members of the class granting friendship can be named in the[*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]")*s* and member declarations of the befriended
class[.](#2.sentence-1)
[*Example [2](#example-2)*: class A {class B { }; friend class X;};
struct X : A::B { // OK, A::B accessible to friend A::B mx; // OK, A::B accessible to member of friendclass Y { A::B my; // OK, A::B accessible to nested member of friend};}; — *end example*]
[*Example [3](#example-3)*: class X {enum { a=100 }; friend class Y;};
class Y {int v[X::a]; // OK, Y is a friend of X};
class Z {int v[X::a]; // error: X::a is private}; — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4984)
A friend declaration that does not declare a function
shall be a [*friend-type-declaration*](class.mem.general#nt:friend-type-declaration "11.4.1General[class.mem.general]")[.](#3.sentence-1)
[*Note [1](#note-1)*:
A friend declaration can be the[*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") in
a [*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]") ([[temp.pre]](temp.pre "13.1Preamble"), [[temp.friend]](temp.friend "13.7.5Friends"))[.](#3.sentence-2)
— *end note*]
If a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1General[class.mem.general]") in a friend declaration
designates a (possibly
cv-qualified) class type, that class is declared as a friend; otherwise, the[*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1General[class.mem.general]") is ignored[.](#3.sentence-3)
[*Example [4](#example-4)*: class C;typedef C Ct;class E;
class X1 {friend C; // OK, class C is a friend};
class X2 {friend Ct; // OK, class C is a friendfriend D; // error: D not foundfriend class D; // OK, elaborated-type-specifier declares new class};
template <typename ... Ts> class R {friend Ts...;};
template <class... Ts, class... Us>class R<R<Ts...>, R<Us...>> {friend Ts::Nested..., Us...;};
R<C> rc; // class C is a friend of R<C> R<C, E> rce; // classes C and E are friends of R<C, E> R<int> Ri; // OK, “friend int;'' is ignoredstruct E { struct Nested; };
R<R<E>, R<C, int>> rr; // E::Nested and C are friends of R<R<E>, R<C, int>> — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5032)
[*Note [2](#note-2)*:
A friend declaration refers to an entity, not (all overloads of) a name[.](#4.sentence-1)
A member function of a classX can be a friend of
a classY[.](#4.sentence-2)
[*Example [5](#example-5)*: class Y {friend char* X::foo(int); friend X::X(char); // constructors can be friendsfriend X::~X(); // destructors can be friends}; — *end example*]
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5053)
A function may be defined in a friend declaration of a class if and only if the
class is a non-local class ([[class.local]](class.local "11.6Local class declarations")) and the function name is unqualified[.](#5.sentence-1)
[*Example [6](#example-6)*: class M {friend void f() { } // definition of global f, a friend of M,// not the definition of a member function}; — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5066)
Such a function is implicitly an inline ([[dcl.inline]](dcl.inline "9.2.8The inline specifier")) function
if it is attached to the global module[.](#6.sentence-1)
[*Note [3](#note-3)*:
If a friend function is defined outside a class,
it is not in the scope of the class[.](#6.sentence-2)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5074)
No[*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") shall appear in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") of a friend declaration[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5081)
A member nominated by a friend declaration shall be accessible in the
class containing the friend declaration[.](#8.sentence-1)
The meaning of the friend declaration is the same whether the friend declaration
appears in the private, protected, or public ([[class.mem]](class.mem "11.4Class members"))
portion of the class[*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]")[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5090)
Friendship is neither inherited nor transitive[.](#9.sentence-1)
[*Example [7](#example-7)*: class A {friend class B; int a;};
class B {friend class C;};
class C {void f(A* p) { p->a++; // error: C is not a friend of A despite being a friend of a friend}};
class D : public B {void f(A* p) { p->a++; // error: D is not a friend of A despite being derived from a friend}}; — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5118)
[*Note [4](#note-4)*:
A friend declaration never binds any names ([[dcl.meaning]](dcl.meaning "9.3.4Meaning of declarators"), [[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers"))[.](#10.sentence-1)
— *end note*]
[*Example [8](#example-8)*: // Assume f and g have not yet been declared.void h(int);template <class T> void f2(T);namespace A {class X {friend void f(X); // A::f(X) is a friendclass Y {friend void g(); // A::g is a friendfriend void h(int); // A::h is a friend// ::h not consideredfriend void f2<>(int); // ::f2<>(int) is a friend}; }; // A::f, A::g and A::h are not visible here X x; void g() { f(x); } // definition of A::gvoid f(X) { /* ... */ } // definition of A::fvoid h(int) { /* ... */ } // definition of A::h// A::f, A::g and A::h are visible here and known to be friends}using A::x;
void h() { A::f(x);
A::X::f(x); // error: f is not a member of A::X A::X::Y::g(); // error: g is not a member of A::X::Y} — *end example*]
[*Example [9](#example-9)*: class X;void a();void f() {class Y; extern void b(); class A {friend class X; // OK, but X is a local class, not ::Xfriend class Y; // OKfriend class Z; // OK, introduces local class Zfriend void a(); // error, ::a is not consideredfriend void b(); // OKfriend void c(); // error};
X* px; // OK, but ::X is found Z* pz; // error: no Z is found} — *end example*]

157
cppdraft/class/gslice.md Normal file
View File

@@ -0,0 +1,157 @@
[class.gslice]
# 29 Numerics library [[numerics]](./#numerics)
## 29.6 Numeric arrays [[numarray]](numarray#class.gslice)
### 29.6.6 The gslice class [class.gslice]
#### [29.6.6.1](#overview) Overview [[class.gslice.overview]](class.gslice.overview)
[🔗](#lib:gslice)
namespace std {class gslice {public: gslice();
gslice(size_t s, const valarray<size_t>& l, const valarray<size_t>& d);
size_t start() const;
valarray<size_t> size() const;
valarray<size_t> stride() const; };}
[1](#overview-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8619)
This class represents a generalized slice out of an array[.](#overview-1.sentence-1)
Agslice is defined by a starting offset (s),
a set of lengths (lj),
and a set of strides (dj)[.](#overview-1.sentence-2)
The number of lengths shall equal the number of strides[.](#overview-1.sentence-3)
[2](#overview-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8628)
Agslice represents a mapping from a set of indices (ij),
equal in number to the number of strides, to a single index k[.](#overview-2.sentence-1)
It is useful for building multidimensional array classes using
thevalarray template, which is one-dimensional[.](#overview-2.sentence-2)
The set of one-dimensional index values specified by a gslice are
k=s+∑jijdj where the multidimensional indices ij range in value from
0 to lij−1[.](#overview-2.sentence-3)
[3](#overview-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8642)
[*Example [1](#overview-example-1)*:
Thegslice specificationstart = 3 length = {2, 4, 3} stride = {19, 4, 1} yields the sequence of one-dimensional indices
k=3+(0,1)×19+(0,1,2,3)×4+(0,1,2)×1 which are ordered as shown in the following table:
```
(i0,i1,i2,k)=
(0,0,0, 3),
(0,0,1, 4),
(0,0,2, 5),
(0,1,0, 7),
(0,1,1, 8),
(0,1,2, 9),
(0,2,0,11),
(0,2,1,12),
(0,2,2,13),
(0,3,0,15),
(0,3,1,16),
(0,3,2,17),
(1,0,0,22),
(1,0,1,23),
(1,3,2,36)
```
That is, the highest-ordered index turns fastest[.](#overview-3.sentence-2)
— *end example*]
[4](#overview-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8680)
It is possible to have degenerate generalized slices in which an address
is repeated[.](#overview-4.sentence-1)
[5](#overview-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8684)
[*Example [2](#overview-example-2)*:
If the stride parameters in the previous
example are changed to {1, 1, 1}, the first few elements of the
resulting sequence of indices will be
```
(0,0,0, 3),
(0,0,1, 4),
(0,0,2, 5),
(0,1,0, 4),
(0,1,1, 5),
(0,1,2, 6),
```
— *end example*]
[6](#overview-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8702)
If a degenerate slice is used as the argument to the
non-const version ofoperator[](const gslice&),
the behavior is undefined[.](#overview-6.sentence-1)
#### [29.6.6.2](#gslice.cons) Constructors [[gslice.cons]](gslice.cons)
[🔗](#lib:gslice,constructor)
`gslice();
gslice(size_t start, const valarray<size_t>& lengths,
const valarray<size_t>& strides);
`
[1](#gslice.cons-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8720)
The default constructor is equivalent togslice(0, valarray<size_t>(), valarray<size_t>())[.](#gslice.cons-1.sentence-1)
The constructor with arguments builds agslice based on a specification of start, lengths, and strides, as explained
in the previous subclause[.](#gslice.cons-1.sentence-2)
#### [29.6.6.3](#gslice.access) Access functions [[gslice.access]](gslice.access)
[🔗](#lib:start,gslice)
`size_t start() const;
valarray<size_t> size() const;
valarray<size_t> stride() const;
`
[1](#gslice.access-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8741)
*Returns*: The representation of the
start, lengths, or strides specified for the gslice[.](#gslice.access-1.sentence-1)
[2](#gslice.access-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8746)
*Complexity*: start() is constant time[.](#gslice.access-2.sentence-1)
size() and stride() are linear in the number of strides[.](#gslice.access-2.sentence-2)

View File

@@ -0,0 +1,115 @@
[class.gslice.overview]
# 29 Numerics library [[numerics]](./#numerics)
## 29.6 Numeric arrays [[numarray]](numarray#class.gslice.overview)
### 29.6.6 The gslice class [[class.gslice]](class.gslice#overview)
#### 29.6.6.1 Overview [class.gslice.overview]
[🔗](#lib:gslice)
namespace std {class gslice {public: gslice();
gslice(size_t s, const valarray<size_t>& l, const valarray<size_t>& d);
size_t start() const;
valarray<size_t> size() const;
valarray<size_t> stride() const; };}
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8619)
This class represents a generalized slice out of an array[.](#1.sentence-1)
Agslice is defined by a starting offset (s),
a set of lengths (lj),
and a set of strides (dj)[.](#1.sentence-2)
The number of lengths shall equal the number of strides[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8628)
Agslice represents a mapping from a set of indices (ij),
equal in number to the number of strides, to a single index k[.](#2.sentence-1)
It is useful for building multidimensional array classes using
thevalarray template, which is one-dimensional[.](#2.sentence-2)
The set of one-dimensional index values specified by a gslice are
k=s+∑jijdj where the multidimensional indices ij range in value from
0 to lij−1[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8642)
[*Example [1](#example-1)*:
Thegslice specificationstart = 3 length = {2, 4, 3} stride = {19, 4, 1} yields the sequence of one-dimensional indices
k=3+(0,1)×19+(0,1,2,3)×4+(0,1,2)×1 which are ordered as shown in the following table:
```
(i0,i1,i2,k)=
(0,0,0, 3),
(0,0,1, 4),
(0,0,2, 5),
(0,1,0, 7),
(0,1,1, 8),
(0,1,2, 9),
(0,2,0,11),
(0,2,1,12),
(0,2,2,13),
(0,3,0,15),
(0,3,1,16),
(0,3,2,17),
(1,0,0,22),
(1,0,1,23),
(1,3,2,36)
```
That is, the highest-ordered index turns fastest[.](#3.sentence-2)
— *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8680)
It is possible to have degenerate generalized slices in which an address
is repeated[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8684)
[*Example [2](#example-2)*:
If the stride parameters in the previous
example are changed to {1, 1, 1}, the first few elements of the
resulting sequence of indices will be
```
(0,0,0, 3),
(0,0,1, 4),
(0,0,2, 5),
(0,1,0, 4),
(0,1,1, 5),
(0,1,2, 6),
```
— *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8702)
If a degenerate slice is used as the argument to the
non-const version ofoperator[](const gslice&),
the behavior is undefined[.](#6.sentence-1)

View File

@@ -0,0 +1,82 @@
[class.inhctor.init]
# 11 Classes [[class]](./#class)
## 11.9 Initialization [[class.init]](class.init#class.inhctor.init)
### 11.9.4 Initialization by inherited constructor [class.inhctor.init]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5966)
When a constructor for type B is invoked
to initialize an object of a different type D (that is, when the constructor was inherited ([[namespace.udecl]](namespace.udecl "9.10The using declaration"))),
initialization proceeds as if a defaulted default constructor
were used to initialize the D object and
each base class subobject from which the constructor was inherited,
except that the B subobject is initialized
by the inherited constructor
if the base class subobject were to be initialized
as part of the D object ([[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#1.sentence-1)
The invocation of the inherited constructor,
including the evaluation of any arguments,
is omitted if the B subobject is not to be initialized
as part of the D object[.](#1.sentence-2)
The complete initialization is considered to be a single function call;
in particular, unless omitted,
the initialization of the inherited constructor's parameters
is sequenced before the initialization of any part of the D object[.](#1.sentence-3)
[*Example [1](#example-1)*: struct B1 { B1(int, ...) { }};
struct B2 { B2(double) { }};
int get();
struct D1 : B1 {using B1::B1; // inherits B1(int, ...)int x; int y = get();};
void test() { D1 d(2, 3, 4); // OK, B1 is initialized by calling B1(2, 3, 4),// then d.x is default-initialized (no initialization is performed),// then d.y is initialized by calling get() D1 e; // error: D1 has no default constructor}struct D2 : B2 {using B2::B2;
B1 b;};
D2 f(1.0); // error: B1 has no default constructorstruct W { W(int); };struct X : virtual W { using W::W; X() = delete; };struct Y : X { using X::X; };struct Z : Y, virtual W { using Y::Y; };
Z z(0); // OK, initialization of Y does not invoke default constructor of Xtemplate<class T> struct Log : T {using T::T; // inherits all constructors from class T~Log() { std::clog << "Destroying wrapper" << std::endl; }};
Class template Log wraps any class and forwards all of its constructors,
while writing a message to the standard log
whenever an object of class Log is destroyed[.](#1.sentence-4)
— *end example*]
[*Example [2](#example-2)*: struct V { V() = default; V(int); };struct Q { Q(); };struct A : virtual V, Q {using V::V;
A() = delete;};int bar() { return 42; }struct B : A { B() : A(bar()) {} // OK};struct C : B {};void foo() { C c; } // bar is not invoked, because the V subobject is not initialized as part of B — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6050)
If the constructor was inherited from multiple base class subobjects
of type B, the program is ill-formed[.](#2.sentence-1)
[*Example [3](#example-3)*: struct A { A(int); };struct B : A { using A::A; };
struct C1 : B { using B::B; };struct C2 : B { using B::B; };
struct D1 : C1, C2 {using C1::C1; using C2::C2;};
struct V1 : virtual B { using B::B; };struct V2 : virtual B { using B::B; };
struct D2 : V1, V2 {using V1::V1; using V2::V2;};
D1 d1(0); // error: ambiguous D2 d2(0); // OK, initializes virtual B base class, which initializes the A base class// then initializes the V1 and V2 base classes as if by a defaulted default constructorstruct M { M(); M(int); };struct N : M { using M::M; };struct O : M {};struct P : N, O { using N::N; using O::O; };
P p(0); // OK, use M(0) to initialize N's base class,// use M() to initialize O's base class — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6087)
When an object is initialized by an inherited constructor,
initialization of the object is complete
when the initialization of all subobjects is complete[.](#3.sentence-1)

856
cppdraft/class/init.md Normal file
View File

@@ -0,0 +1,856 @@
[class.init]
# 11 Classes [[class]](./#class)
## 11.9 Initialization [class.init]
### [11.9.1](#general) General [[class.init.general]](class.init.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5343)
When no initializer is specified for an object of (possibly
cv-qualified) class type (or array thereof), or the initializer has
the form(),
the object is initialized as specified in [[dcl.init]](dcl.init "9.5Initializers")[.](#general-1.sentence-1)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5350)
An object of class type (or array thereof) can be explicitly initialized;
see [[class.expl.init]](#class.expl.init "11.9.2Explicit initialization") and [[class.base.init]](#class.base.init "11.9.3Initializing bases and members")[.](#general-2.sentence-1)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5354)
When an array of class objects is initialized
(either explicitly or implicitly) and the elements are initialized by constructor,
the constructor shall be called for each element of the array,
following the subscript order; see [[dcl.array]](dcl.array "9.3.4.5Arrays")[.](#general-3.sentence-1)
[*Note [1](#general-note-1)*:
Destructors for the array elements are called in reverse order of their
construction[.](#general-3.sentence-2)
— *end note*]
### [11.9.2](#class.expl.init) Explicit initialization [[class.expl.init]](class.expl.init)
[1](#class.expl.init-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5369)
An object of class type can be initialized with a parenthesized[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]"),
where the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") is construed as an argument list for a constructor
that is called to initialize the object[.](#class.expl.init-1.sentence-1)
Alternatively, a single[*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") can be specified as an[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") using the= form of initialization[.](#class.expl.init-1.sentence-2)
Either direct-initialization semantics or copy-initialization semantics apply;
see [[dcl.init]](dcl.init "9.5Initializers")[.](#class.expl.init-1.sentence-3)
[*Example [1](#class.expl.init-example-1)*: struct complex { complex();
complex(double);
complex(double,double);};
complex sqrt(complex,complex);
complex a(1); // initialized by calling complex(double) with argument 1 complex b = a; // initialized as a copy of a complex c = complex(1,2); // initialized by calling complex(double,double) with arguments 1 and 2 complex d = sqrt(b,c); // initialized by calling sqrt(complex,complex) with d as its result object complex e; // initialized by calling complex() complex f = 3; // initialized by calling complex(double) with argument 3 complex g = { 1, 2 }; // initialized by calling complex(double, double) with arguments 1 and 2 — *end example*]
[*Note [1](#class.expl.init-note-1)*:
Overloading of the assignment operator ([[over.assign]](over.assign "12.4.3.2Simple assignment"))
has no effect on initialization[.](#class.expl.init-1.sentence-4)
— *end note*]
[2](#class.expl.init-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5410)
An object of class type can also be initialized by a[*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")[.](#class.expl.init-2.sentence-1)
List-initialization semantics apply;
see [[dcl.init]](dcl.init "9.5Initializers") and [[dcl.init.list]](dcl.init.list "9.5.5List-initialization")[.](#class.expl.init-2.sentence-2)
[*Example [2](#class.expl.init-example-2)*: complex v[6] = { 1, complex(1,2), complex(), 2 };
Here,complex::complex(double) is called for the initialization ofv[0] andv[3],complex::complex(double, double) is called for the initialization ofv[1],complex::complex() is called for the initialization ofv[2],v[4],
andv[5][.](#class.expl.init-2.sentence-3)
For another example,
struct X {int i; float f;
complex c;} x = { 99, 88.8, 77.7 };
Here,x.i is initialized with 99,x.f is initialized with 88.8, andcomplex::complex(double) is called for the initialization ofx.c[.](#class.expl.init-2.sentence-5)
— *end example*]
[*Note [2](#class.expl.init-note-2)*:
Braces can be elided in the[*initializer-list*](dcl.init.general#nt:initializer-list "9.5.1General[dcl.init.general]") for any aggregate, even if the aggregate has members of a class type with
user-defined type conversions; see [[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates")[.](#class.expl.init-2.sentence-6)
— *end note*]
[3](#class.expl.init-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5462)
[*Note [3](#class.expl.init-note-3)*:
IfT is a class type with no default constructor,
any initializing declaration of an object of typeT (or array thereof) is ill-formed if no[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") is explicitly specified (see [class.init] and [[dcl.init]](dcl.init "9.5Initializers"))[.](#class.expl.init-3.sentence-1)
— *end note*]
[4](#class.expl.init-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5474)
[*Note [4](#class.expl.init-note-4)*:
The order in which objects with static or thread storage duration
are initialized is described in [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3Dynamic initialization of non-block variables") and [[stmt.dcl]](stmt.dcl "8.10Declaration statement")[.](#class.expl.init-4.sentence-1)
— *end note*]
### [11.9.3](#class.base.init) Initializing bases and members [[class.base.init]](class.base.init)
[1](#class.base.init-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5485)
In the definition of a constructor for a class,
initializers for direct and virtual base class subobjects and
non-static data members can be specified by a[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]"),
which has the form
[ctor-initializer:](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]")
: [*mem-initializer-list*](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]")
[mem-initializer-list:](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]")
[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") ...opt
[*mem-initializer-list*](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]") , [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") ...opt
[mem-initializer:](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")
[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")opt )
[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]")
[mem-initializer-id:](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]")
[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1General[class.derived.general]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[2](#class.base.init-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5514)
Lookup for an unqualified name in a [*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") ignores the constructor's function parameter scope[.](#class.base.init-2.sentence-1)
[*Note [1](#class.base.init-note-1)*:
If the constructor's class contains a member with the same name as a direct
or virtual base class of the class, a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") naming the member or base class and composed of a single identifier
refers to the class member[.](#class.base.init-2.sentence-2)
A[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") for the hidden base class can be specified using a qualified name[.](#class.base.init-2.sentence-3)
— *end note*]
Unless the[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") names the constructor's class,
a non-static data member of the constructor's class, or
a direct or virtual base of that class,
the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is ill-formed[.](#class.base.init-2.sentence-4)
[3](#class.base.init-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5536)
A[*mem-initializer-list*](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]") can initialize a base class using any [*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1General[class.derived.general]") that denotes that base class type[.](#class.base.init-3.sentence-1)
[*Example [1](#class.base.init-example-1)*: struct A { A(); };typedef A global_A;struct B { };struct C: public A, public B { C(); };
C::C(): global_A() { } // mem-initializer for base A — *end example*]
[4](#class.base.init-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5550)
If a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") is ambiguous because it designates both a direct non-virtual base class and
an indirect virtual base class, the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is ill-formed[.](#class.base.init-4.sentence-1)
[*Example [2](#class.base.init-example-2)*: struct A { A(); };struct B: public virtual A { };struct C: public A, public B { C(); };
C::C(): A() { } // error: which A? — *end example*]
[5](#class.base.init-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5566)
A[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") may initialize a variant member of the
constructor's class[.](#class.base.init-5.sentence-1)
If a[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") specifies more than one[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") for the same member or for the same base class,
the[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") is ill-formed[.](#class.base.init-5.sentence-2)
[6](#class.base.init-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5580)
A [*mem-initializer-list*](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]") can delegate to another
constructor of the constructor's class using any[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1General[class.derived.general]") that denotes the constructor's class itself[.](#class.base.init-6.sentence-1)
If a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") designates the constructor's class,
it shall be the only [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]"); the constructor
is a [*delegating constructor*](#def:constructor,delegating "11.9.3Initializing bases and members[class.base.init]"), and the constructor selected by the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is the [*target constructor*](#def:constructor,target "11.9.3Initializing bases and members[class.base.init]")[.](#class.base.init-6.sentence-2)
The target constructor is selected by overload resolution[.](#class.base.init-6.sentence-3)
Once the target constructor returns, the body of the delegating constructor
is executed[.](#class.base.init-6.sentence-4)
If a constructor delegates to itself directly or indirectly,
the program is ill-formed, no diagnostic required[.](#class.base.init-6.sentence-5)
[*Example [3](#class.base.init-example-3)*: struct C { C( int ) { } // #1: non-delegating constructor C(): C(42) { } // #2: delegates to #1 C( char c ) : C(42.0) { } // #3: ill-formed due to recursion with #4 C( double d ) : C('a') { } // #4: ill-formed due to recursion with #3}; — *end example*]
[7](#class.base.init-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5603)
The[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") in a[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is used to initialize the
designated subobject (or, in the case of a delegating constructor, the complete class object)
according to the initialization rules of [[dcl.init]](dcl.init "9.5Initializers") for direct-initialization[.](#class.base.init-7.sentence-1)
[*Example [4](#class.base.init-example-4)*: struct B1 { B1(int); /* ... */ };struct B2 { B2(int); /* ... */ };struct D : B1, B2 { D(int);
B1 b; const int c;};
D::D(int a) : B2(a+1), B1(a+2), c(a+3), b(a+4) { /* ... */ } D d(10); — *end example*]
[*Note [2](#class.base.init-note-2)*:
The initialization
performed by each [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") constitutes a full-expression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))[.](#class.base.init-7.sentence-2)
Any expression in
a[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is evaluated as part of the full-expression that performs the initialization[.](#class.base.init-7.sentence-3)
— *end note*]
A [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") where the [*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") denotes
a virtual base class is ignored during execution of a constructor of any class that is
not the most derived class[.](#class.base.init-7.sentence-4)
[8](#class.base.init-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5641)
A temporary expression bound to a reference member in a [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is ill-formed[.](#class.base.init-8.sentence-1)
[*Example [5](#class.base.init-example-5)*: struct A { A() : v(42) { } // errorconst int& v;}; — *end example*]
[9](#class.base.init-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5653)
In a non-delegating constructor
other than an implicitly-defined copy/move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")),
if a given potentially constructed subobject is not designated by a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") (including the case where there is no[*mem-initializer-list*](#nt:mem-initializer-list "11.9.3Initializing bases and members[class.base.init]") because the constructor has no[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]")),
then
- [(9.1)](#class.base.init-9.1)
if the entity is a non-static data member that has
a default member initializer ([[class.mem]](class.mem "11.4Class members")) and either
* [(9.1.1)](#class.base.init-9.1.1)
the constructor's class is a union ([[class.union]](class.union "11.5Unions")), and no other variant
member of that union is designated by a [*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") or
* [(9.1.2)](#class.base.init-9.1.2)
the constructor's class is not a union, and, if the entity is a member of an
anonymous union, no other member of that union is designated by a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]"),
the entity is initialized from its default member initializer
as specified in [[dcl.init]](dcl.init "9.5Initializers");
- [(9.2)](#class.base.init-9.2)
otherwise, if the entity is an anonymous union or a variant member ([[class.union.anon]](class.union.anon "11.5.2Anonymous unions")), no initialization is performed;
- [(9.3)](#class.base.init-9.3)
otherwise, the entity is default-initialized ([[dcl.init]](dcl.init "9.5Initializers"))[.](#class.base.init-9.sentence-1)
[*Note [3](#class.base.init-note-3)*:
An abstract class ([[class.abstract]](class.abstract "11.7.4Abstract classes")) is never a most derived
class, thus its constructors never initialize virtual base classes, therefore the
corresponding [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")*s* can be omitted[.](#class.base.init-9.sentence-2)
— *end note*]
An attempt to initialize more than one non-static data member of a union renders the
program ill-formed[.](#class.base.init-9.sentence-3)
[*Note [4](#class.base.init-note-4)*:
After the call to a constructor for classX for an object with automatic or dynamic storage duration
has completed, if
the constructor was not invoked as part of value-initialization and
a member ofX is neither initialized nor
given a value
during execution of the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of the body of the constructor,
the member has an indeterminate or erroneous value ([[basic.indet]](basic.indet "6.8.5Indeterminate and erroneous values"))[.](#class.base.init-9.sentence-4)
— *end note*]
[*Example [6](#class.base.init-example-6)*: struct A { A();};
struct B { B(int);};
struct C { C() { } // initializes members as follows: A a; // OK, calls A::A()const B b; // error: B has no default constructorint i; // OK, i has indeterminate or erroneous valueint j = 5; // OK, j has the value 5}; — *end example*]
[10](#class.base.init-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5724)
If a given non-static data member has both a default member initializer
and a [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]"), the initialization specified by the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is performed, and the non-static data member's
default member initializer is ignored[.](#class.base.init-10.sentence-1)
[*Example [7](#class.base.init-example-7)*:
Givenstruct A {int i = /* some integer expression with side effects */ ;
A(int arg) : i(arg) { }// ...}; the A(int) constructor will simply initialize i to the value ofarg, and theside effects in i's default member initializer
will not take place[.](#class.base.init-10.sentence-2)
— *end example*]
[11](#class.base.init-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5748)
A temporary expression bound to a reference member from a
default member initializer is ill-formed[.](#class.base.init-11.sentence-1)
[*Example [8](#class.base.init-example-8)*: struct A { A() = default; // OK A(int v) : v(v) { } // OKconst int& v = 42; // OK};
A a1; // error: ill-formed binding of temporary to reference A a2(1); // OK, unfortunately — *end example*]
[12](#class.base.init-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5763)
In a non-delegating constructor, the destructor for each potentially constructed
subobject of class type is potentially invoked ([[class.dtor]](class.dtor "11.4.7Destructors"))[.](#class.base.init-12.sentence-1)
[*Note [5](#class.base.init-note-5)*:
This provision ensures that destructors can be called for fully-constructed
subobjects in case an exception is thrown ([[except.ctor]](except.ctor "14.3Stack unwinding"))[.](#class.base.init-12.sentence-2)
— *end note*]
[13](#class.base.init-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5771)
In a non-delegating constructor, initialization
proceeds in the following order:
- [(13.1)](#class.base.init-13.1)
First, and only for the constructor of the most derived class ([[intro.object]](intro.object "6.8.2Object model")),
virtual base classes are initialized in the order they appear on a
depth-first left-to-right traversal of the directed acyclic graph of
base classes,
where “left-to-right” is the order of appearance of the base classes
in the derived class[*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]")[.](#class.base.init-13.1.sentence-1)
- [(13.2)](#class.base.init-13.2)
Then, direct base classes are initialized in declaration order
as they appear in the[*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]") (regardless of the order of the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")*s*)[.](#class.base.init-13.2.sentence-1)
- [(13.3)](#class.base.init-13.3)
Then, non-static data members are initialized in the order
they were declared in the class definition
(again regardless of the order of the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")*s*)[.](#class.base.init-13.3.sentence-1)
- [(13.4)](#class.base.init-13.4)
Finally, the [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") of the constructor
body is executed[.](#class.base.init-13.4.sentence-1)
[*Note [6](#class.base.init-note-6)*:
The declaration order is mandated to ensure that base and member
subobjects are destroyed in the reverse order of initialization[.](#class.base.init-13.sentence-2)
— *end note*]
[14](#class.base.init-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5807)
[*Example [9](#class.base.init-example-9)*: struct V { V();
V(int);};
struct A : virtual V { A();
A(int);};
struct B : virtual V { B();
B(int);};
struct C : A, B, virtual V { C();
C(int);};
A::A(int i) : V(i) { /* ... */ } B::B(int i) { /* ... */ } C::C(int i) { /* ... */ } V v(1); // use V(int) A a(2); // use V(int) B b(3); // use V() C c(4); // use V() — *end example*]
[15](#class.base.init-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5841)
[*Note [7](#class.base.init-note-7)*:
The [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") of a [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") is in the function parameter scope of the constructor
and can use this to refer to the object being initialized[.](#class.base.init-15.sentence-1)
— *end note*]
[*Example [10](#class.base.init-example-10)*: class X {int a; int b; int i; int j;public:const int& r;
X(int i): r(a), b(i), i(i), j(this->i) { }};
initializesX::r to refer toX::a,
initializesX::b with the value of the constructor parameteri,
initializesX::i with the value of the constructor parameteri,
and initializesX::j with the value ofX::i;
this takes place each time an object of classX is created[.](#class.base.init-15.sentence-2)
— *end example*]
[16](#class.base.init-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5883)
Member functions (including virtual member functions, [[class.virtual]](class.virtual "11.7.3Virtual functions")) can be
called for an object under construction or destruction[.](#class.base.init-16.sentence-1)
Similarly, an object under construction or destruction can be the operand of thetypeid operator ([[expr.typeid]](expr.typeid "7.6.1.8Type identification")) or of adynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7Dynamic cast"))[.](#class.base.init-16.sentence-2)
However, if these operations are performed
during evaluation of
- [(16.1)](#class.base.init-16.1)
a [*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") (or in a function called directly or indirectly from a[*ctor-initializer*](#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]"))
before all the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]")*s* for base classes have completed,
- [(16.2)](#class.base.init-16.2)
a precondition assertion of a constructor, or
- [(16.3)](#class.base.init-16.3)
a postcondition assertion of a destructor ([[dcl.contract.func]](dcl.contract.func "9.4.1General")),
the program has undefined behavior[.](#class.base.init-16.sentence-3)
[*Example [11](#class.base.init-example-11)*: class A {public: A(int);};
class B : public A {int j;public:int f();
B() : A(f()), // undefined behavior: calls member function but base A not yet initialized j(f()) { } // well-defined: bases are all initialized};
class C {public: C(int);};
class D : public B, C {int i;public: D() : C(f()), // undefined behavior: calls member function but base C not yet initialized i(f()) { } // well-defined: bases are all initialized}; — *end example*]
[17](#class.base.init-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5936)
[*Note [8](#class.base.init-note-8)*:
[[class.cdtor]](#class.cdtor "11.9.5Construction and destruction") describes the results of virtual function calls,typeid anddynamic_casts
during construction for the well-defined cases;
that is, describes the polymorphic behavior
of an object under construction[.](#class.base.init-17.sentence-1)
— *end note*]
[18](#class.base.init-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5947)
A [*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") followed by an ellipsis is
a pack expansion ([[temp.variadic]](temp.variadic "13.7.4Variadic templates")) that initializes the base
classes specified by a pack expansion in the [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1General[class.derived.general]") for the class[.](#class.base.init-18.sentence-1)
[*Example [12](#class.base.init-example-12)*: template<class... Mixins>class X : public Mixins... {public: X(const Mixins&... mixins) : Mixins(mixins)... { }}; — *end example*]
### [11.9.4](#class.inhctor.init) Initialization by inherited constructor [[class.inhctor.init]](class.inhctor.init)
[1](#class.inhctor.init-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5966)
When a constructor for type B is invoked
to initialize an object of a different type D (that is, when the constructor was inherited ([[namespace.udecl]](namespace.udecl "9.10The using declaration"))),
initialization proceeds as if a defaulted default constructor
were used to initialize the D object and
each base class subobject from which the constructor was inherited,
except that the B subobject is initialized
by the inherited constructor
if the base class subobject were to be initialized
as part of the D object ([[class.base.init]](#class.base.init "11.9.3Initializing bases and members"))[.](#class.inhctor.init-1.sentence-1)
The invocation of the inherited constructor,
including the evaluation of any arguments,
is omitted if the B subobject is not to be initialized
as part of the D object[.](#class.inhctor.init-1.sentence-2)
The complete initialization is considered to be a single function call;
in particular, unless omitted,
the initialization of the inherited constructor's parameters
is sequenced before the initialization of any part of the D object[.](#class.inhctor.init-1.sentence-3)
[*Example [1](#class.inhctor.init-example-1)*: struct B1 { B1(int, ...) { }};
struct B2 { B2(double) { }};
int get();
struct D1 : B1 {using B1::B1; // inherits B1(int, ...)int x; int y = get();};
void test() { D1 d(2, 3, 4); // OK, B1 is initialized by calling B1(2, 3, 4),// then d.x is default-initialized (no initialization is performed),// then d.y is initialized by calling get() D1 e; // error: D1 has no default constructor}struct D2 : B2 {using B2::B2;
B1 b;};
D2 f(1.0); // error: B1 has no default constructorstruct W { W(int); };struct X : virtual W { using W::W; X() = delete; };struct Y : X { using X::X; };struct Z : Y, virtual W { using Y::Y; };
Z z(0); // OK, initialization of Y does not invoke default constructor of Xtemplate<class T> struct Log : T {using T::T; // inherits all constructors from class T~Log() { std::clog << "Destroying wrapper" << std::endl; }};
Class template Log wraps any class and forwards all of its constructors,
while writing a message to the standard log
whenever an object of class Log is destroyed[.](#class.inhctor.init-1.sentence-4)
— *end example*]
[*Example [2](#class.inhctor.init-example-2)*: struct V { V() = default; V(int); };struct Q { Q(); };struct A : virtual V, Q {using V::V;
A() = delete;};int bar() { return 42; }struct B : A { B() : A(bar()) {} // OK};struct C : B {};void foo() { C c; } // bar is not invoked, because the V subobject is not initialized as part of B — *end example*]
[2](#class.inhctor.init-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6050)
If the constructor was inherited from multiple base class subobjects
of type B, the program is ill-formed[.](#class.inhctor.init-2.sentence-1)
[*Example [3](#class.inhctor.init-example-3)*: struct A { A(int); };struct B : A { using A::A; };
struct C1 : B { using B::B; };struct C2 : B { using B::B; };
struct D1 : C1, C2 {using C1::C1; using C2::C2;};
struct V1 : virtual B { using B::B; };struct V2 : virtual B { using B::B; };
struct D2 : V1, V2 {using V1::V1; using V2::V2;};
D1 d1(0); // error: ambiguous D2 d2(0); // OK, initializes virtual B base class, which initializes the A base class// then initializes the V1 and V2 base classes as if by a defaulted default constructorstruct M { M(); M(int); };struct N : M { using M::M; };struct O : M {};struct P : N, O { using N::N; using O::O; };
P p(0); // OK, use M(0) to initialize N's base class,// use M() to initialize O's base class — *end example*]
[3](#class.inhctor.init-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6087)
When an object is initialized by an inherited constructor,
initialization of the object is complete
when the initialization of all subobjects is complete[.](#class.inhctor.init-3.sentence-1)
### [11.9.5](#class.cdtor) Construction and destruction [[class.cdtor]](class.cdtor)
[1](#class.cdtor-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6097)
For an object with a non-trivial constructor, referring to any non-static member
or base class of the object before the constructor begins execution results in
undefined behavior[.](#class.cdtor-1.sentence-1)
For an object with a non-trivial destructor, referring to
any non-static member or base class of the object after the destructor finishes
execution results in undefined behavior[.](#class.cdtor-1.sentence-2)
[*Example [1](#class.cdtor-example-1)*: struct X { int i; };struct Y : X { Y(); }; // non-trivialstruct A { int a; };struct B : public A { int j; Y y; }; // non-trivialextern B bobj;
B* pb = &bobj; // OKint* p1 = &bobj.a; // undefined behavior: refers to base class memberint* p2 = &bobj.y.i; // undefined behavior: refers to member's member A* pa = &bobj; // undefined behavior: upcast to a base class type B bobj; // definition of bobjextern X xobj;int* p3 = &xobj.i; // OK, all constructors of X are trivial X xobj;
For another example,struct W { int j; };struct X : public virtual W { };struct Y {int* p;
X x;
Y() : p(&x.j) { // undefined, x is not yet constructed}};
— *end example*]
[2](#class.cdtor-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6137)
During the construction of an object,
if the value of any of its subobjects
or any element of its object representation
is accessed through a glvalue that is not obtained, directly or indirectly, from
the constructor'sthis pointer, the value thus obtained is unspecified[.](#class.cdtor-2.sentence-1)
[*Example [2](#class.cdtor-example-2)*: struct C;void no_opt(C*);
struct C {int c;
C() : c(0) { no_opt(this); }};
const C cobj;
void no_opt(C* cptr) {int i = cobj.c * 100; // value of cobj.c is unspecified cptr->c = 1;
cout << cobj.c * 100 // value of cobj.c is unspecified<< '\n';}extern struct D d;struct D { D(int a) : a(a), b(d.a) {}int a, b;};
D d = D(1); // value of d.b is unspecified — *end example*]
[3](#class.cdtor-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6173)
To explicitly or implicitly convert a pointer (a glvalue) referring to
an object of classX to a pointer (reference) to a direct or indirect base classB ofX,
the construction ofX and the construction of all of its direct or indirect bases that directly or
indirectly derive fromB shall have started and the destruction of these classes shall not have
completed, otherwise the conversion results in undefined behavior[.](#class.cdtor-3.sentence-1)
To form a pointer to (or access the value of) a direct non-static member of
an objectobj,
the construction ofobj shall have started and its destruction shall not have completed,
otherwise the computation of the pointer value (or accessing the member
value) results in undefined behavior[.](#class.cdtor-3.sentence-2)
[*Example [3](#class.cdtor-example-3)*: struct A { };struct B : virtual A { };struct C : B { };struct D : virtual A { D(A*); };struct X { X(A*); };
struct E : C, D, X { E() : D(this), // undefined behavior: upcast from E* to A* might use path E* → D* → A*// but D is not constructed// “D((C*)this)'' would be defined: E* → C* is defined because E() has started,// and C* → A* is defined because C is fully constructed X(this) {} // defined: upon construction of X, C/B/D/A sublattice is fully constructed}; — *end example*]
[4](#class.cdtor-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6218)
Member functions, including virtual functions ([[class.virtual]](class.virtual "11.7.3Virtual functions")), can be called
during construction or destruction ([[class.base.init]](#class.base.init "11.9.3Initializing bases and members"))[.](#class.cdtor-4.sentence-1)
When a virtual function is called directly or indirectly from a constructor
or from a destructor,
including during the construction or destruction of the class's non-static data
members,
or during the evaluation of
a postcondition assertion of a constructor or
a precondition assertion of a destructor ([[dcl.contract.func]](dcl.contract.func "9.4.1General")),
and the object to which the call applies is the object (call it x) under construction or
destruction,
the function called is the
final overrider in the constructor's or destructor's class and not one
overriding it in a more-derived class[.](#class.cdtor-4.sentence-2)
If the virtual function call uses an explicit class member access ([[expr.ref]](expr.ref "7.6.1.5Class member access"))
and the object expression refers to
the complete object of x or one of that object's base class subobjects
but not x or one of its base class subobjects, the behavior
is undefined[.](#class.cdtor-4.sentence-3)
[*Example [4](#class.cdtor-example-4)*: struct V {virtual void f(); virtual void g();};
struct A : virtual V {virtual void f();};
struct B : virtual V {virtual void g();
B(V*, A*);};
struct D : A, B {virtual void f(); virtual void g();
D() : B((A*)this, this) { }};
B::B(V* v, A* a) { f(); // calls V::f, not A::f g(); // calls B::g, not D::g v->g(); // v is base of B, the call is well-defined, calls B::g a->f(); // undefined behavior: a's type not a base of B} — *end example*]
[5](#class.cdtor-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6273)
Thetypeid operator ([[expr.typeid]](expr.typeid "7.6.1.8Type identification")) can be used during construction or destruction ([[class.base.init]](#class.base.init "11.9.3Initializing bases and members"))[.](#class.cdtor-5.sentence-1)
Whentypeid is used in a constructor (including the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") or default member initializer ([[class.mem]](class.mem "11.4Class members"))
for a non-static data member)
or in a destructor, or used in a function called (directly or indirectly) from
a constructor or destructor, if the operand oftypeid refers to the object under construction or destruction,typeid yields thestd::type_info object representing the constructor or destructor's class[.](#class.cdtor-5.sentence-2)
If the operand oftypeid refers to the object under construction or destruction and the static type of
the operand is neither the constructor or destructor's class nor one of its
bases, the behavior is undefined[.](#class.cdtor-5.sentence-3)
[6](#class.cdtor-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6300)
dynamic_casts ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7Dynamic cast")) can be used during construction
or destruction ([[class.base.init]](#class.base.init "11.9.3Initializing bases and members"))[.](#class.cdtor-6.sentence-1)
When adynamic_cast is used in a constructor (including the[*mem-initializer*](#nt:mem-initializer "11.9.3Initializing bases and members[class.base.init]") or default member initializer
for a non-static data member)
or in a destructor, or used in a function called (directly or indirectly) from
a constructor or destructor, if the operand of thedynamic_cast refers to the object under construction or destruction, this object is
considered to be a most derived object that has the type of the constructor or
destructor's class[.](#class.cdtor-6.sentence-2)
If the operand of thedynamic_cast refers to the object under construction or destruction and the static type of
the operand is not a pointer to or object of the constructor or destructor's
own class or one of its bases, thedynamic_cast results in undefined behavior[.](#class.cdtor-6.sentence-3)
[*Example [5](#class.cdtor-example-5)*: struct V {virtual void f();};
struct A : virtual V { };
struct B : virtual V { B(V*, A*);};
struct D : A, B { D() : B((A*)this, this) { }};
B::B(V* v, A* a) {typeid(*this); // type_info for Btypeid(*v); // well-defined: *v has type V, a base of B yields type_info for Btypeid(*a); // undefined behavior: type A not a base of Bdynamic_cast<B*>(v); // well-defined: v of type V*, V base of B results in B*dynamic_cast<B*>(a); // undefined behavior: a has type A*, A not a base of B} — *end example*]
### [11.9.6](#class.copy.elision) Copy/move elision [[class.copy.elision]](class.copy.elision)
[1](#class.copy.elision-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6354)
When certain criteria are met, an implementation is
allowed to omit the creation of a class object from
a source object of the same type (ignoring cv-qualification),
even if the selected constructor and/or the
destructor for the object haveside effects[.](#class.copy.elision-1.sentence-1)
In such cases, the
implementation treats the source and target of the
omitted initialization as simply two different ways of
referring to the same object[.](#class.copy.elision-1.sentence-2)
If the first parameter of the
selected constructor is an rvalue reference to the object's type,
the destruction of that object occurs when the target would have been destroyed;
otherwise, the destruction occurs at the later of the times when the
two objects would have been destroyed without the
optimization[.](#class.copy.elision-1.sentence-3)
[*Note [1](#class.copy.elision-note-1)*:
Because only one object is destroyed instead of two,
and the creation of one object is omitted,
there is still one object destroyed for each one constructed[.](#class.copy.elision-1.sentence-4)
— *end note*]
This elision of object creation, called[*copy elision*](#def:copy_elision),
is permitted in the
following circumstances (which may be combined to
eliminate multiple copies):
- [(1.1)](#class.copy.elision-1.1)
in a return statement ([[stmt.return]](stmt.return "8.8.4The return statement")) in
a function with a class return type,
when the [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is the name of a non-volatile
object o with automatic storage duration (other than a function parameter or a variable
introduced by the [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") of a[*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") ([[except.handle]](except.handle "14.4Handling an exception"))),
the copy-initialization of the result object can be
omitted by constructing o directly
into the function call's result object;
- [(1.2)](#class.copy.elision-1.2)
in a [*throw-expression*](expr.throw#nt:throw-expression "7.6.18Throwing an exception[expr.throw]") ([[expr.throw]](expr.throw "7.6.18Throwing an exception")), when the operand
is the name of a non-volatile object o with automatic storage duration
(other than a function parameter or
a variable introduced by
the [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") of a [*handler*](except.pre#nt:handler "14.1Preamble[except.pre]"))
that belongs to a scope that does not contain
the innermost enclosing [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]") associated with a [*try-block*](except.pre#nt:try-block "14.1Preamble[except.pre]") (if there is one),
the copy-initialization of the exception object can be omitted by
constructing o directly into the exception object;
- [(1.3)](#class.copy.elision-1.3)
in a [coroutine](dcl.fct.def.coroutine "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"), a copy of a coroutine parameter
can be omitted and references to that copy replaced with references to the
corresponding parameter if the meaning of the program will be unchanged except for
the execution of a constructor and destructor for the parameter copy object;
- [(1.4)](#class.copy.elision-1.4)
when the [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") of a[*handler*](except.pre#nt:handler "14.1Preamble[except.pre]") ([[except.handle]](except.handle "14.4Handling an exception")) declares an object o,
the copy-initialization of o can be omitted by treating
the [*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]") as an alias for the exception
object if the meaning of the program will be unchanged except for the execution
of constructors and destructors for the object declared by the[*exception-declaration*](except.pre#nt:exception-declaration "14.1Preamble[except.pre]")[.](#class.copy.elision-1.sentence-5)
[*Note [2](#class.copy.elision-note-2)*:
There cannot be a move from the exception object because it is
always an lvalue[.](#class.copy.elision-1.4.sentence-2)
— *end note*]
Copy elision is not permitted
where an expression is evaluated in a context
requiring a constant expression ([[expr.const]](expr.const "7.7Constant expressions"))
and in constant initialization ([[basic.start.static]](basic.start.static "6.10.3.2Static initialization"))[.](#class.copy.elision-1.sentence-6)
[*Note [3](#class.copy.elision-note-3)*:
It is possible that copy elision is performed
if the same expression
is evaluated in another context[.](#class.copy.elision-1.sentence-7)
— *end note*]
[2](#class.copy.elision-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6436)
[*Example [1](#class.copy.elision-example-1)*: class Thing {public: Thing(); ~Thing();
Thing(const Thing&);};
Thing f() { Thing t; return t;} Thing t2 = f();
struct A {void *p; constexpr A(): p(this) {}};
constexpr A g() { A loc; return loc;}constexpr A a; // well-formed, a.p points to aconstexpr A b = g(); // error: b.p would be dangling ([[expr.const]](expr.const "7.7Constant expressions"))void h() { A c = g(); // well-formed, c.p can point to c or be dangling}
Here the criteria for elision can eliminate
the copying of the object t with automatic storage duration
into the result object for the function call f(),
which is the non-local object t2[.](#class.copy.elision-2.sentence-1)
Effectively, the construction of t can be viewed as directly initializing t2,
and that object's destruction will occur at program exit[.](#class.copy.elision-2.sentence-2)
Adding a move constructor to Thing has the same effect, but it is the
move construction from the object with automatic storage duration to t2 that is elided[.](#class.copy.elision-2.sentence-3)
— *end example*]
[3](#class.copy.elision-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6481)
[*Example [2](#class.copy.elision-example-2)*: class Thing {public: Thing(); ~Thing();
Thing(Thing&&);private: Thing(const Thing&);};
Thing f(bool b) { Thing t; if (b)throw t; // OK, Thing(Thing&&) used (or elided) to throw treturn t; // OK, Thing(Thing&&) used (or elided) to return t} Thing t2 = f(false); // OK, no extra copy/move performed, t2 constructed by call to fstruct Weird { Weird();
Weird(Weird&);};
Weird g(bool b) {static Weird w1;
Weird w2; if (b)return w1; // OK, uses Weird(Weird&)elsereturn w2; // error: w2 in this context is an xvalue}int& h(bool b, int i) {static int s; if (b)return s; // OKelsereturn i; // error: i is an xvalue}decltype(auto) h2(Thing t) {return t; // OK, t is an xvalue and h2's return type is Thing}decltype(auto) h3(Thing t) {return (t); // OK, (t) is an xvalue and h3's return type is Thing&&} — *end example*]
[4](#class.copy.elision-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6534)
[*Example [3](#class.copy.elision-example-3)*: template<class T> void g(const T&);
template<class T> void f() { T x; try { T y; try { g(x); }catch (...) {if (/*...*/)throw x; // does not movethrow y; // moves} g(y); } catch(...) { g(x);
g(y); // error: y is not in scope}} — *end example*]

View File

@@ -0,0 +1,39 @@
[class.init.general]
# 11 Classes [[class]](./#class)
## 11.9 Initialization [[class.init]](class.init#general)
### 11.9.1 General [class.init.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5343)
When no initializer is specified for an object of (possibly
cv-qualified) class type (or array thereof), or the initializer has
the form(),
the object is initialized as specified in [[dcl.init]](dcl.init "9.5Initializers")[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5350)
An object of class type (or array thereof) can be explicitly initialized;
see [[class.expl.init]](class.expl.init "11.9.2Explicit initialization") and [[class.base.init]](class.base.init "11.9.3Initializing bases and members")[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5354)
When an array of class objects is initialized
(either explicitly or implicitly) and the elements are initialized by constructor,
the constructor shall be called for each element of the array,
following the subscript order; see [[dcl.array]](dcl.array "9.3.4.5Arrays")[.](#3.sentence-1)
[*Note [1](#note-1)*:
Destructors for the array elements are called in reverse order of their
construction[.](#3.sentence-2)
— *end note*]

56
cppdraft/class/local.md Normal file
View File

@@ -0,0 +1,56 @@
[class.local]
# 11 Classes [[class]](./#class)
## 11.6 Local class declarations [class.local]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3443)
A class can be declared within a function definition; such a class is
called a [*local class*](#def:class,local "11.6Local class declarations[class.local]")[.](#1.sentence-1)
[*Note [1](#note-1)*:
A declaration in a local class
cannot odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule"))
a local entity
from an
enclosing scope[.](#1.sentence-2)
— *end note*]
[*Example [1](#example-1)*: int x;void f() {static int s; int x; const int N = 5; extern int q(); int arr[2]; auto [y, z] = arr; struct local {int g() { return x; } // error: odr-use of non-odr-usable variable xint h() { return s; } // OKint k() { return ::x; } // OKint l() { return q(); } // OKint m() { return N; } // OK, not an odr-useint* n() { return &N; } // error: odr-use of non-odr-usable variable Nint p() { return y; } // error: odr-use of non-odr-usable structured binding y};} local* p = 0; // error: local not found — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3479)
An enclosing function has no special access to members of the local
class; it obeys the usual access rules ([[class.access]](class.access "11.8Member access control"))[.](#2.sentence-1)
Member functions of a local class shall be defined within their class
definition, if they are defined at all[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3486)
A class nested within
a local class is a local class[.](#3.sentence-1)
A member of a local class X shall be
declared only in the definition of X or,
if the member is a nested class,
in the nearest enclosing block scope of X[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3496)
[*Note [2](#note-2)*:
A local class cannot have static data members ([[class.static.data]](class.static.data "11.4.9.3Static data members"))[.](#4.sentence-1)
— *end note*]

2816
cppdraft/class/mem.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,659 @@
[class.mem.general]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#general)
### 11.4.1 General [class.mem.general]
[member-specification:](#nt:member-specification "11.4.1General[class.mem.general]")
[*member-declaration*](#nt:member-declaration "11.4.1General[class.mem.general]") [*member-specification*](#nt:member-specification "11.4.1General[class.mem.general]")opt
[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1General[class.derived.general]") : [*member-specification*](#nt:member-specification "11.4.1General[class.mem.general]")opt
[member-declaration:](#nt:member-declaration "11.4.1General[class.mem.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")opt [*member-declarator-list*](#nt:member-declarator-list "11.4.1General[class.mem.general]")opt ;
[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1General[dcl.fct.def.general]")
[*friend-type-declaration*](#nt:friend-type-declaration "11.4.1General[class.mem.general]")
[*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")
[*using-enum-declaration*](enum.udecl#nt:using-enum-declaration "9.8.2The using enum declaration[enum.udecl]")
[*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1Preamble[dcl.pre]")
[*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1Preamble[dcl.pre]")
[*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]")
[*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4Explicit specialization[temp.expl.spec]")
[*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3Deduction guides[temp.deduct.guide]")
[*alias-declaration*](dcl.pre#nt:alias-declaration "9.1Preamble[dcl.pre]")
[*opaque-enum-declaration*](dcl.enum#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]")
[*empty-declaration*](dcl.pre#nt:empty-declaration "9.1Preamble[dcl.pre]")
[member-declarator-list:](#nt:member-declarator-list "11.4.1General[class.mem.general]")
[*member-declarator*](#nt:member-declarator "11.4.1General[class.mem.general]")
[*member-declarator-list*](#nt:member-declarator-list "11.4.1General[class.mem.general]") , [*member-declarator*](#nt:member-declarator "11.4.1General[class.mem.general]")
[member-declarator:](#nt:member-declarator "11.4.1General[class.mem.general]")
[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") [*virt-specifier-seq*](#nt:virt-specifier-seq "11.4.1General[class.mem.general]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt [*pure-specifier*](#nt:pure-specifier "11.4.1General[class.mem.general]")opt
[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt
[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt : [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")opt
[virt-specifier-seq:](#nt:virt-specifier-seq "11.4.1General[class.mem.general]")
[*virt-specifier*](#nt:virt-specifier "11.4.1General[class.mem.general]") [*virt-specifier-seq*](#nt:virt-specifier-seq "11.4.1General[class.mem.general]")opt
[virt-specifier:](#nt:virt-specifier "11.4.1General[class.mem.general]")
override
final
[pure-specifier:](#nt:pure-specifier "11.4.1General[class.mem.general]")
= 0
[friend-type-declaration:](#nt:friend-type-declaration "11.4.1General[class.mem.general]")
friend [*friend-type-specifier-list*](#nt:friend-type-specifier-list "11.4.1General[class.mem.general]") ;
[friend-type-specifier-list:](#nt:friend-type-specifier-list "11.4.1General[class.mem.general]")
[*friend-type-specifier*](#nt:friend-type-specifier "11.4.1General[class.mem.general]") ...opt
[*friend-type-specifier-list*](#nt:friend-type-specifier-list "11.4.1General[class.mem.general]") , [*friend-type-specifier*](#nt:friend-type-specifier "11.4.1General[class.mem.general]") ...opt
[friend-type-specifier:](#nt:friend-type-specifier "11.4.1General[class.mem.general]")
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3Simple type specifiers[dcl.type.simple]")
[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]")
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1General[temp.res.general]")
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L616)
In the absence of a [*virt-specifier-seq*](#nt:virt-specifier-seq "11.4.1General[class.mem.general]"),
the token sequence = 0 is treated as a [*pure-specifier*](#nt:pure-specifier "11.4.1General[class.mem.general]") if the type of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") ([[dcl.meaning.general]](dcl.meaning.general "9.3.4.1General"))
is a function type, and
is otherwise treated as a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")[.](#1.sentence-1)
[*Note [1](#note-1)*:
If the member declaration acquires a function type through
template instantiation,
the program is ill-formed; see [[temp.spec.general]](temp.spec.general "13.9.1General")[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L628)
The optional [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]") ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))
in a [*member-declarator*](#nt:member-declarator "11.4.1General[class.mem.general]") shall be present only if
the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") declares a function[.](#2.sentence-1)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L634)
The [*member-specification*](#nt:member-specification "11.4.1General[class.mem.general]") in a class definition declares the
full set of members of the class; no member can be added elsewhere[.](#3.sentence-1)
A [*direct member*](#def:member,direct "11.4.1General[class.mem.general]") of a class X is a member of X that was first declared within the [*member-specification*](#nt:member-specification "11.4.1General[class.mem.general]") of X,
including anonymous union members ([[class.union.anon]](class.union.anon "11.5.2Anonymous unions")) and direct members thereof[.](#3.sentence-2)
Members of a class are data members, member
functions ([[class.mfct]](class.mfct "11.4.2Member functions")), nested types, enumerators,
and member templates ([[temp.mem]](temp.mem "13.7.3Member templates")) and specializations thereof[.](#3.sentence-3)
[*Note [2](#note-2)*:
A specialization of a static data member template is a static data member[.](#3.sentence-4)
A specialization of a member function template is a member function[.](#3.sentence-5)
A specialization of a member class template is a nested class[.](#3.sentence-6)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L650)
A [*member-declaration*](#nt:member-declaration "11.4.1General[class.mem.general]") does not itself declare new members of the class
if it is
- [(4.1)](#4.1)
a friend declaration ([[class.friend]](class.friend "11.8.4Friends")),
- [(4.2)](#4.2)
a [*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3Deduction guides[temp.deduct.guide]") ([[temp.deduct.guide]](temp.deduct.guide "13.7.2.3Deduction guides")),
- [(4.3)](#4.3)
a [*template-declaration*](temp.pre#nt:template-declaration "13.1Preamble[temp.pre]") whose [*declaration*](dcl.pre#nt:declaration "9.1Preamble[dcl.pre]") is one of the above,
- [(4.4)](#4.4)
a [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1Preamble[dcl.pre]"),
- [(4.5)](#4.5)
a [*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1Preamble[dcl.pre]"),
- [(4.6)](#4.6)
a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10The using declaration")), or
- [(4.7)](#4.7)
an [*empty-declaration*](dcl.pre#nt:empty-declaration "9.1Preamble[dcl.pre]")[.](#4.sentence-1)
For any other [*member-declaration*](#nt:member-declaration "11.4.1General[class.mem.general]"),
each declared entity
that is not an [unnamed bit-field](class.bit#def:bit-field,unnamed "11.4.10Bit-fields[class.bit]") is a member of the class,
and each such [*member-declaration*](#nt:member-declaration "11.4.1General[class.mem.general]") shall either
declare at least one member name of the class
or declare at least one unnamed bit-field[.](#4.sentence-2)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L671)
A [*data member*](#def:data_member "11.4.1General[class.mem.general]") is a non-function member introduced by a[*member-declarator*](#nt:member-declarator "11.4.1General[class.mem.general]")[.](#5.sentence-1)
A [*member function*](#def:member_function "11.4.1General[class.mem.general]") is a member that is a function[.](#5.sentence-2)
Nested types are classes ([[class.name]](class.name "11.3Class names"), [[class.nest]](class.nest "11.4.12Nested class declarations")) and
enumerations ([[dcl.enum]](dcl.enum "9.8.1Enumeration declarations")) declared in the class and arbitrary types
declared as members by use of a typedef declaration ([[dcl.typedef]](dcl.typedef "9.2.4The typedef specifier"))
or [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1Preamble[dcl.pre]")[.](#5.sentence-3)
The enumerators of an [unscoped enumeration](dcl.enum "9.8.1Enumeration declarations[dcl.enum]") defined in the class
are members of the class[.](#5.sentence-4)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L682)
A data member or member function
may be declared static in its [*member-declaration*](#nt:member-declaration "11.4.1General[class.mem.general]"),
in which case it is a [*static member*](#def:member,static "11.4.1General[class.mem.general]") (see [[class.static]](class.static "11.4.9Static members"))
(a [*static data member*](#def:data_member,static "11.4.1General[class.mem.general]") ([[class.static.data]](class.static.data "11.4.9.3Static data members")) or[*static member function*](#def:member_function,static "11.4.1General[class.mem.general]") ([[class.static.mfct]](class.static.mfct "11.4.9.2Static member functions")), respectively)
of the class[.](#6.sentence-1)
Any other data member or member function is a [*non-static member*](#def:member,non-static "11.4.1General[class.mem.general]") (a [*non-static data member*](#def:data_member,non-static "11.4.1General[class.mem.general]") or[*non-static member function*](#def:member_function,non-static "11.4.1General[class.mem.general]") ([[class.mfct.non.static]](class.mfct.non.static "11.4.3Non-static member functions")), respectively)[.](#6.sentence-2)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L693)
Every object of class type has a unique member subobject
corresponding to each of its direct non-static data members[.](#7.sentence-1)
If any non-static data member of a class C is of reference type,
then let D be an invented class
that is identical to C except that each non-static member of D corresponding to
a member of C of type “reference to T”
instead has type “pointer to T”[.](#7.sentence-2)
Every member subobject of a complete object of type C has the same size, alignment, and offset
as that of the corresponding subobject of a complete object of type D[.](#7.sentence-3)
The size and alignment of C are the same as
the size and alignment of D[.](#7.sentence-4)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L708)
A member shall not be declared twice in the[*member-specification*](#nt:member-specification "11.4.1General[class.mem.general]"), except that
- [(8.1)](#8.1)
a nested class or member
class template can be declared and then later defined, and
- [(8.2)](#8.2)
an
enumeration can be introduced with an [*opaque-enum-declaration*](dcl.enum#nt:opaque-enum-declaration "9.8.1Enumeration declarations[dcl.enum]") and later
redeclared with an [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]")[.](#8.sentence-1)
[*Note [3](#note-3)*:
A single name can denote several member functions provided their types
are sufficiently different ([[basic.scope.scope]](basic.scope.scope "6.4.1General"))[.](#8.sentence-2)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L723)
A redeclaration of a class member outside its class definition shall be
a definition,
an explicit specialization, or
an explicit instantiation ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization"), [[temp.explicit]](temp.explicit "13.9.3Explicit instantiation"))[.](#9.sentence-1)
The member shall not be a non-static data member[.](#9.sentence-2)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L730)
A [*complete-class context*](#def:complete-class_context "11.4.1General[class.mem.general]") of a class (template) is a
- [(10.1)](#10.1)
function body ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1General")),
- [(10.2)](#10.2)
default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments")),
- [(10.3)](#10.3)
default template argument ([[temp.param]](temp.param "13.2Template parameters")),
- [(10.4)](#10.4)
[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]") ([[except.spec]](except.spec "14.5Exception specifications")),
- [(10.5)](#10.5)
[*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1General[dcl.contract.func]") ([[dcl.contract.func]](dcl.contract.func "9.4.1General")), or
- [(10.6)](#10.6)
default member initializer
within the [*member-specification*](#nt:member-specification "11.4.1General[class.mem.general]") of the class or class template[.](#10.sentence-1)
[*Note [4](#note-4)*:
A complete-class context of a nested class is also a complete-class
context of any enclosing class, if the nested class is defined within
the [*member-specification*](#nt:member-specification "11.4.1General[class.mem.general]") of the enclosing class[.](#10.sentence-2)
— *end note*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L748)
A class C is complete at a program point P if the definition of C is reachable from P ([[module.reach]](module.reach "10.7Reachability"))
or if P is in a complete-class context of C[.](#11.sentence-1)
Otherwise, C is incomplete at P[.](#11.sentence-2)
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L754)
If a [*member-declaration*](#nt:member-declaration "11.4.1General[class.mem.general]") matches
the syntactic requirements of [*friend-type-declaration*](#nt:friend-type-declaration "11.4.1General[class.mem.general]"),
it is a [*friend-type-declaration*](#nt:friend-type-declaration "11.4.1General[class.mem.general]")[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L759)
In a [*member-declarator*](#nt:member-declarator "11.4.1General[class.mem.general]"),
an = immediately following the [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") is interpreted as introducing a [*pure-specifier*](#nt:pure-specifier "11.4.1General[class.mem.general]") if the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") has function type,
otherwise it is interpreted as introducing
a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")[.](#13.sentence-1)
[*Example [1](#example-1)*: struct S {using T = void();
T * p = 0; // OK, [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")virtual T f = 0; // OK, [*pure-specifier*](#nt:pure-specifier "11.4.1General[class.mem.general]")}; — *end example*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L776)
In a [*member-declarator*](#nt:member-declarator "11.4.1General[class.mem.general]") for a bit-field,
the [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]") is parsed as
the longest sequence of tokens
that could syntactically form a [*constant-expression*](expr.const#nt:constant-expression "7.7Constant expressions[expr.const]")[.](#14.sentence-1)
[*Example [2](#example-2)*: int a;const int b = 0;struct S {int x1 : 8 = 42; // OK, "= 42" is [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")int x2 : 8 { 42 }; // OK, "{ 42 }" is [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")int y1 : true ? 8 : a = 42; // OK, [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") is absentint y2 : true ? 8 : b = 42; // error: cannot assign to const intint y3 : (true ? 8 : b) = 42; // OK, "= 42" is [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")int z : 1 || new int { 0 }; // OK, [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") is absent}; — *end example*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L796)
A [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") shall appear only in the
declaration of a data member[.](#15.sentence-1)
(For static data members,
see [[class.static.data]](class.static.data "11.4.9.3Static data members"); for non-static data members,
see [[class.base.init]](class.base.init "11.9.3Initializing bases and members") and [[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates"))[.](#15.sentence-2)
A [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") for a non-static data memberspecifies a [*default member initializer*](#def:default_member_initializer "11.4.1General[class.mem.general]") for the member, and
shall not directly or indirectly cause the implicit definition of a
defaulted default constructor for the enclosing class or the
exception specification of that constructor[.](#15.sentence-3)
An immediate invocation ([[expr.const]](expr.const "7.7Constant expressions")) that
is a potentially-evaluated subexpression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))
of a default member initializer
is neither evaluated nor checked for whether it
is a constant expression at the point where the subexpression appears[.](#15.sentence-4)
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L813)
A member shall not be declared with the extern[*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]")[.](#16.sentence-1)
Within a class definition, a member shall not be declared with the thread_local [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") unless also declared static[.](#16.sentence-2)
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L817)
The [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") may be omitted in constructor, destructor,
and conversion function declarations only;
when declaring another kind of member the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]") shall contain a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") that is not a [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")[.](#17.sentence-1)
The[*member-declarator-list*](#nt:member-declarator-list "11.4.1General[class.mem.general]") can be omitted only after a[*class-specifier*](class.pre#nt:class-specifier "11.1Preamble[class.pre]") or an [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1Enumeration declarations[dcl.enum]") or in a[friend declaration](class.friend "11.8.4Friends[class.friend]")[.](#17.sentence-2)
A[*pure-specifier*](#nt:pure-specifier "11.4.1General[class.mem.general]") shall be used only in the declaration of a[virtual function](class.virtual "11.7.3Virtual functions[class.virtual]") that is not a friend declaration[.](#17.sentence-3)
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L830)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*member-declaration*](#nt:member-declaration "11.4.1General[class.mem.general]") appertains to each of the entities declared by the [*member-declarator*](#nt:member-declarator "11.4.1General[class.mem.general]")*s*;
it shall not appear if the optional [*member-declarator-list*](#nt:member-declarator-list "11.4.1General[class.mem.general]") is omitted[.](#18.sentence-1)
[19](#19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L835)
A [*virt-specifier-seq*](#nt:virt-specifier-seq "11.4.1General[class.mem.general]") shall contain at most one of each[*virt-specifier*](#nt:virt-specifier "11.4.1General[class.mem.general]")[.](#19.sentence-1)
A [*virt-specifier-seq*](#nt:virt-specifier-seq "11.4.1General[class.mem.general]") shall appear only in the first declaration of a virtual member
function ([[class.virtual]](class.virtual "11.7.3Virtual functions"))[.](#19.sentence-2)
[20](#20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L842)
The type of a non-static data member shall not be an
incomplete type ([[basic.types.general]](basic.types.general#term.incomplete.type "6.9.1General")),
an abstract class type ([[class.abstract]](class.abstract "11.7.4Abstract classes")),
or a (possibly multidimensional) array thereof[.](#20.sentence-1)
[*Note [5](#note-5)*:
In particular, a class C cannot contain
a non-static member of class C,
but it can contain a pointer or reference to an object of class C[.](#20.sentence-2)
— *end note*]
[21](#21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L854)
[*Note [6](#note-6)*:
See [[expr.prim.id]](expr.prim.id "7.5.5Names") for restrictions on the use of non-static data
members and non-static member functions[.](#21.sentence-1)
— *end note*]
[22](#22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L860)
[*Note [7](#note-7)*:
The type of a non-static member function is an ordinary function type,
and the type of a non-static data member is an ordinary object type[.](#22.sentence-1)
There are no special member function types or data member types[.](#22.sentence-2)
— *end note*]
[23](#23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L867)
[*Example [3](#example-3)*:
A simple example of a class definition isstruct tnode {char tword[20]; int count;
tnode* left;
tnode* right;}; which contains an array of twenty characters, an integer, and two
pointers to objects of the same type[.](#23.sentence-1)
Once this definition has been
given, the declarationtnode s, *sp; declares s to be a tnode and sp to be a pointer
to a tnode[.](#23.sentence-2)
With these declarations, sp->count refers to
the count member of the object to which sp points;s.left refers to the left subtree pointer of the objects; and s.right->tword[0] refers to the initial character
of the tword member of the right subtree of s[.](#23.sentence-3)
— *end example*]
[24](#24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L892)
[*Note [8](#note-8)*:
Non-variant non-static data members of
non-zero size ([[intro.object]](intro.object "6.8.2Object model"))
are allocated so that later
members have higher addresses within a class object ([[expr.rel]](expr.rel "7.6.9Relational operators"))[.](#24.sentence-1)
Implementation alignment requirements can cause two adjacent members
not to be allocated immediately after each other; so can requirements
for space for managing virtual functions ([[class.virtual]](class.virtual "11.7.3Virtual functions")) and
virtual base classes ([[class.mi]](class.mi "11.7.2Multiple base classes"))[.](#24.sentence-2)
— *end note*]
[25](#25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L905)
If T is the name of a class, then each of the following shall
have a name different from T:
- [(25.1)](#25.1)
every static data member of class T;
- [(25.2)](#25.2)
every member function of class T;
[*Note [9](#note-9)*:
This restriction does not apply to constructors, which do not have
names ([[class.ctor]](class.ctor "11.4.5Constructors"))[.](#25.2.sentence-1)
— *end note*]
- [(25.3)](#25.3)
every member of class T that is itself a type;
- [(25.4)](#25.4)
every member template of class T;
- [(25.5)](#25.5)
every enumerator of every member of class T that is an
unscoped enumeration type; and
- [(25.6)](#25.6)
every member of every anonymous union that is a member of classT[.](#25.sentence-1)
[26](#26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L928)
In addition, if class T has a user-declared[constructor](class.ctor "11.4.5Constructors[class.ctor]"), every non-static data member of classT shall have a name different from T[.](#26.sentence-1)
[27](#27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L933)
The [*common initial sequence*](#def:common_initial_sequence "11.4.1General[class.mem.general]") of two standard-layout struct ([[class.prop]](class.prop "11.2Properties of classes"))
types is the longest sequence of non-static data
members and bit-fields in declaration order, starting with the first
such entity in each of the structs, such that
- [(27.1)](#27.1)
corresponding entities
have layout-compatible types ([[basic.types]](basic.types "6.9Types")),
- [(27.2)](#27.2)
corresponding entities have the same alignment requirements ([[basic.align]](basic.align "6.8.3Alignment")),
- [(27.3)](#27.3)
if a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2Conditional inclusion[cpp.cond]") ([[cpp.cond]](cpp.cond "15.2Conditional inclusion"))
is not 0 for the no_unique_address attribute,
then neither entity is declared with
the no_unique_address attribute ([[dcl.attr.nouniqueaddr]](dcl.attr.nouniqueaddr "9.13.11No unique address attribute")), and
- [(27.4)](#27.4)
either both entities are bit-fields with the same width
or neither is a bit-field[.](#27.sentence-1)
[*Example [4](#example-4)*: struct A { int a; char b; };struct B { const int b1; volatile char b2; };struct C { int c; unsigned : 0; char b; };struct D { int d; char b : 4; };struct E { unsigned int e; char b; };
The common initial sequence of A and B comprises all members
of either class[.](#27.sentence-2)
The common initial sequence of A and C and
of A and D comprises the first member in each case[.](#27.sentence-3)
The common initial sequence of A and E is empty[.](#27.sentence-4)
— *end example*]
[28](#28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L967)
Two standard-layout struct ([[class.prop]](class.prop "11.2Properties of classes")) types are[*layout-compatible classes*](#def:layout-compatible,class "11.4.1General[class.mem.general]") if
their common initial sequence comprises all members and bit-fields of
both classes ([[basic.types]](basic.types "6.9Types"))[.](#28.sentence-1)
[29](#29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L973)
Two standard-layout unions are layout-compatible if they
have the same number of non-static data members and corresponding
non-static data members (in any order) have layout-compatible
types ([[basic.types.general]](basic.types.general#term.layout.compatible.type "6.9.1General"))[.](#29.sentence-1)
[30](#30)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L979)
In a standard-layout union with an [active member](class.union#def:active,union_member "11.5Unions[class.union]") of struct type T1, it is permitted to read a non-static
data member m of another union member of struct type T2 provided m is part of the common initial sequence of T1 and T2;
the behavior is as if the corresponding member of T1 were nominated[.](#30.sentence-1)
[*Example [5](#example-5)*: struct T1 { int a, b; };struct T2 { int c; double d; };union U { T1 t1; T2 t2; };int f() { U u = { { 1, 2 } }; // active member is t1return u.t2.c; // OK, as if u.t1.a were nominated} — *end example*]
[*Note [10](#note-10)*:
Reading a volatile object through a glvalue of non-volatile type has
undefined behavior ([[dcl.type.cv]](dcl.type.cv "9.2.9.2The cv-qualifiers"))[.](#30.sentence-2)
— *end note*]
[31](#31)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1001)
If a standard-layout class object has any non-static data members, its address
is the same as the address of its first non-static data member
if that member is not a bit-field[.](#31.sentence-1)
Its
address is also the same as the address of each of its base class subobjects[.](#31.sentence-2)
[*Note [11](#note-11)*:
There can therefore be unnamed padding within a standard-layout struct object
inserted by an implementation, but
not at its beginning, as necessary to achieve appropriate alignment[.](#31.sentence-3)
— *end note*]
[*Note [12](#note-12)*:
The object and its first subobject are
pointer-interconvertible ([[basic.compound]](basic.compound "6.9.4Compound types"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"))[.](#31.sentence-4)
— *end note*]
[32](#32)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1016)
A [*data member description*](#def:description,data_member "11.4.1General[class.mem.general]") is
a quintuple (T, N, A, W, NUA)
describing the potential declaration of a non-static data member where
- [(32.1)](#32.1)
T is a type,
- [(32.2)](#32.2)
N is an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") or ⊥,
- [(32.3)](#32.3)
A is an alignment or ⊥,
- [(32.4)](#32.4)
W is a bit-field width or ⊥, and
- [(32.5)](#32.5)
NUA is a boolean value[.](#32.sentence-1)
Two data member descriptions are equal
if each of their respective components are the same entities,
are the same identifiers, have equal values, or are both ⊥[.](#32.sentence-2)
[*Note [13](#note-13)*:
The components of a data member description describe a data member such that
- [(32.6)](#32.6)
its type is specified using the type given by T,
- [(32.7)](#32.7)
it is declared with the name given by N if N is not ⊥ and is otherwise unnamed,
- [(32.8)](#32.8)
it is declared with the [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") ([[dcl.align]](dcl.align "9.13.2Alignment specifier"))
given by alignas(A) if A is not ⊥ and
is otherwise declared without an [*alignment-specifier*](dcl.attr.grammar#nt:alignment-specifier "9.13.1Attribute syntax and semantics[dcl.attr.grammar]"),
- [(32.9)](#32.9)
it is a bit-field ([[class.bit]](class.bit "11.4.10Bit-fields")) with the width given by W if W is not ⊥ and is otherwise not a bit-field, and
- [(32.10)](#32.10)
it is declared with
the attribute [[no_unique_address]] ([[dcl.attr.nouniqueaddr]](dcl.attr.nouniqueaddr "9.13.11No unique address attribute"))
if NUA is true and is otherwise declared without that attribute[.](#32.sentence-3)
Data member descriptions are represented by reflections ([[basic.fundamental]](basic.fundamental "6.9.2Fundamental types"))
returned by std::meta::data_member_spec ([[meta.reflection.define.aggregate]](meta.reflection.define.aggregate "21.4.16Reflection class definition generation")) and
can be reified as data members of a class using std::meta::define_aggregate[.](#32.sentence-4)
— *end note*]

View File

@@ -0,0 +1,213 @@
[class.member.lookup]
# 6 Basics [[basic]](./#basic)
## 6.5 Name lookup [[basic.lookup]](basic.lookup#class.member.lookup)
### 6.5.2 Member name lookup [class.member.lookup]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1735)
A [*search*](#def:search "6.5.2Member name lookup[class.member.lookup]") in a scope X for a name M from a program point P is a single search in X for M from P unless X is the scope of a class or class template T, in which case the
following steps define the result of the search[.](#1.sentence-1)
[*Note [1](#note-1)*:
The result differs only
if M is a [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]") or
if the single search would find nothing[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1747)
The [*lookup set*](#def:lookup_set "6.5.2Member name lookup[class.member.lookup]") for a name N in a class or class template C, called S(N,C),
consists of two component sets:
the [*declaration set*](#def:declaration_set), a set of members named N; and
the [*subobject set*](#def:subobject_set),
a set of subobjects where declarations of these members were found
(possibly via [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")*s*)[.](#2.sentence-1)
In the declaration set, type declarations (including injected-class-names)
are replaced by the types they designate[.](#2.sentence-2)
S(N,C) is calculated as follows:
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1757)
The declaration set is the result of
a single search in the scope of C for N from immediately after the [*class-specifier*](class.pre#nt:class-specifier "11.1Preamble[class.pre]") of C if P is in a complete-class context of C or
from P otherwise[.](#3.sentence-1)
If the resulting declaration set is not empty, the subobject set
contains C itself, and calculation is complete[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1766)
Otherwise (i.e., C does not contain a declaration of N or the resulting declaration set is empty), S(N,C) is initially empty[.](#4.sentence-1)
Calculate the lookup set for N in each direct non-dependent ([[temp.dep.type]](temp.dep.type "13.8.3.2Dependent types")) base class subobject Bi, and
merge each such lookup set S(N,Bi) in turn into S(N,C)[.](#4.sentence-2)
[*Note [2](#note-2)*:
If C is incomplete,
only base classes whose [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]") appears before P are considered[.](#4.sentence-3)
If C is an instantiated class, its base classes are not dependent[.](#4.sentence-4)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1779)
The following steps define the result of merging lookup set S(N,Bi) into the intermediate S(N,C):
- [(5.1)](#5.1)
If each of the subobject members of S(N,Bi) is a base class
subobject of at least one of the subobject members of S(N,C), or ifS(N,Bi) is empty, S(N,C) is unchanged and the merge is complete[.](#5.1.sentence-1)
Conversely, if each of the subobject members of S(N,C) is a base class
subobject of at least one of the subobject members of S(N,Bi), or ifS(N,C) is empty, the new S(N,C) is a copy of S(N,Bi)[.](#5.1.sentence-2)
- [(5.2)](#5.2)
Otherwise, if the declaration sets of S(N,Bi) and S(N,C) differ, the merge is ambiguous: the new S(N,C) is a lookup set with an
invalid declaration set and the union of the subobject sets[.](#5.2.sentence-1)
In
subsequent merges, an invalid declaration set is considered different
from any other[.](#5.2.sentence-2)
- [(5.3)](#5.3)
Otherwise, the new S(N,C) is a lookup set with the shared set of
declarations and the union of the subobject sets[.](#5.3.sentence-1)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1801)
The result of the search is the declaration set of S(M,T)[.](#6.sentence-1)
If it is an invalid set, the program is ill-formed[.](#6.sentence-2)
If it differs from the result of a search in T for M in a complete-class context ([[class.mem]](class.mem "11.4Class members")) of T,
the program is ill-formed, no diagnostic required[.](#6.sentence-3)
[*Example [1](#example-1)*: struct A { int x; }; // S(x,A) = { { A::x }, { A } }struct B { float x; }; // S(x,B) = { { B::x }, { B } }struct C: public A, public B { }; // S(x,C) = { invalid, { A in C, B in C } }struct D: public virtual C { }; // S(x,D) = S(x,C)struct E: public virtual C { char x; }; // S(x,E) = { { E::x }, { E } }struct F: public D, public E { }; // S(x,F) = S(x,E)int main() { F f;
f.x = 0; // OK, lookup finds E::x}
S(x,F) is unambiguous because the A and B base
class subobjects of D are also base class subobjects of E, soS(x,D) is discarded in the first merge step[.](#6.sentence-4)
— *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1826)
If M is a non-dependent [*conversion-function-id*](class.conv.fct#nt:conversion-function-id "11.4.8.3Conversion functions[class.conv.fct]"),
conversion function templates that are members of T are considered[.](#7.sentence-1)
For each such template F, the lookup set S(t,T) is constructed,
considering a function template declaration to have the name t only if it corresponds to a declaration of F ([[basic.scope.scope]](basic.scope.scope "6.4.1General"))[.](#7.sentence-2)
The members of the declaration set of each such lookup set,
which shall not be an invalid set, are included in the result[.](#7.sentence-3)
[*Note [3](#note-3)*:
Overload resolution will discard those
that cannot convert to the type specified by M ([[temp.over]](temp.over "13.10.4Overload resolution"))[.](#7.sentence-4)
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1839)
[*Note [4](#note-4)*:
A static member, a nested type or an enumerator defined in a base classT can unambiguously be found even if an object has more than one
base class subobject of type T[.](#8.sentence-1)
Two base class subobjects share
the non-static member subobjects of their common virtual base classes[.](#8.sentence-2)
— *end note*]
[*Example [2](#example-2)*: struct V {int v;};struct A {int a; static int s; enum { e };};struct B : A, virtual V { };struct C : A, virtual V { };struct D : B, C { };
void f(D* pd) { pd->v++; // OK, only one v (virtual) pd->s++; // OK, only one s (static)int i = pd->e; // OK, only one e (enumerator) pd->a++; // error: ambiguous: two as in D} — *end example*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1869)
[*Note [5](#note-5)*:
When virtual base classes are used, a hidden declaration can be reached
along a path through the subobject lattice that does not pass through
the hiding declaration[.](#9.sentence-1)
This is not an ambiguity[.](#9.sentence-2)
The identical use with
non-virtual base classes is an ambiguity; in that case there is no
unique instance of the name that hides all the others[.](#9.sentence-3)
— *end note*]
[*Example [3](#example-3)*: struct V { int f(); int x; };struct W { int g(); int y; };struct B : virtual V, W {int f(); int x; int g(); int y;};struct C : virtual V, W { };
struct D : B, C { void glorp(); };
![SVG Image](data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwLjAwIDAuMDAgMzg2LjAwIDE0MC4wMCIgd2lkdGg9IjM4NnB0IiBoZWlnaHQ9IjE0MHB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4KdmlydAoKPGcgY2xhc3M9Im5vZGUiPgpXMQpXCjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KVgpWCjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KVzIKVwo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+CkIKQgo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkItJmd0O1cxCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik05NC4yNiwtNzYuMTZDODEuODUsLTg0LjQzIDYzLjM3LC05Ni43NSA0OC45MiwtMTA2LjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpCLSZndDtWCjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0xMjEuNzQsLTc2LjE2QzEzNC4xNSwtODQuNDMgMTUyLjYzLC05Ni43NSAxNjcuMDgsLTEwNi4zOCIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQwpDCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQy0mZ3Q7Vgo8cGF0aCBmaWxsPSJub25lIiBkPSJNMjU2LjI2LC03Ni4xNkMyNDMuODUsLTg0LjQzIDIyNS4zNywtOTYuNzUgMjEwLjkyLC0xMDYuMzgiIHN0cm9rZT0iYmxhY2siIC8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiAvPgo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkMtJmd0O1cyCjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0yODMuNzQsLTc2LjE2QzI5Ni4xNSwtODQuNDMgMzE0LjYzLC05Ni43NSAzMjkuMDgsLTEwNi4zOCIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KRApECjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KRC0mZ3Q7Qgo8cGF0aCBzdHJva2U9ImJsYWNrIiBkPSJNMTc1LjI2LC0yMC4xNkMxNjIuODUsLTI4LjQzIDE0NC4zNywtNDAuNzUgMTI5LjkyLC01MC4zOCIgZmlsbD0ibm9uZSIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KRC0mZ3Q7Qwo8cGF0aCBzdHJva2U9ImJsYWNrIiBmaWxsPSJub25lIiBkPSJNMjAyLjc0LC0yMC4xNkMyMTUuMTUsLTI4LjQzIDIzMy42MywtNDAuNzUgMjQ4LjA4LC01MC4zOCIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KPC9nPgo8L3N2Zz4=)
Figure [1](#fig:class.lookup) — Name lookup [[fig:class.lookup]](./fig:class.lookup)
As illustrated in Figure [1](#fig:class.lookup),
the names declared in V and the left-hand instance of W are hidden by those in B, but the names declared in the
right-hand instance of W are not hidden at all[.](#9.sentence-4)
void D::glorp() { x++; // OK, B::x hides V::x f(); // OK, B::f() hides V::f() y++; // error: B::y and C's W::y g(); // error: B::g() and C's W::g()} — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1912)
An explicit or implicit conversion from a pointer to or
an expression designating an object
of a
derived class to a pointer or reference to one of its base classes shall
unambiguously refer to a unique object representing the base class[.](#10.sentence-1)
[*Example [4](#example-4)*: struct V { };struct A { };struct B : A, virtual V { };struct C : A, virtual V { };struct D : B, C { };
void g() { D d;
B* pb = &d;
A* pa = &d; // error: ambiguous: C's A or B's A? V* pv = &d; // OK, only one V subobject} — *end example*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L1935)
[*Note [6](#note-6)*:
Even if the result of name lookup is unambiguous, use of a name found in
multiple subobjects might still be
ambiguous ([[conv.mem]](conv.mem "7.3.13Pointer-to-member conversions"), [[expr.ref]](expr.ref "7.6.1.5Class member access"), [[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members"))[.](#11.sentence-1)
— *end note*]
[*Example [5](#example-5)*: struct B1 {void f(); static void f(int); int i;};struct B2 {void f(double);};struct I1: B1 { };struct I2: B1 { };
struct D: I1, I2, B2 {using B1::f; using B2::f; void g() { f(); // Ambiguous conversion of this f(0); // Unambiguous (static) f(0.0); // Unambiguous (only one B2)int B1::* mpB1 = &D::i; // Unambiguousint D::* mpD = &D::i; // Ambiguous conversion}}; — *end example*]

64
cppdraft/class/mfct.md Normal file
View File

@@ -0,0 +1,64 @@
[class.mfct]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.mfct)
### 11.4.2 Member functions [class.mfct]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1059)
If a member function is attached to the global module and is defined ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions")) in its class definition,
it is inline ([[dcl.inline]](dcl.inline "9.2.8The inline specifier"))[.](#1.sentence-1)
[*Note [1](#note-1)*:
A member function is also inline if it is declaredinline, constexpr, or consteval[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1069)
[*Example [1](#example-1)*: struct X {typedef int T; static T count; void f(T);};void X::f(T t = count) { }
The definition of the member function f of class X inhabits the global
scope; the notation X::f indicates that the function f is a member of class X and in the scope of class X[.](#2.sentence-1)
In
the function definition, the parameter type T refers to the
typedef member T declared in class X and the default
argument count refers to the static data member count declared in class X[.](#2.sentence-2)
— *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1090)
Member functions of a local class shall be defined inline in their class
definition, if they are defined at all[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1095)
[*Note [2](#note-2)*:
A member function can be declared (but not defined) using a typedef for
a function type[.](#4.sentence-1)
The resulting member function has exactly the same type
as it would have if the function declarator were provided explicitly,
see [[dcl.fct]](dcl.fct "9.3.4.6Functions") and [[temp.arg]](temp.arg "13.4Template arguments")[.](#4.sentence-2)
[*Example [2](#example-2)*: typedef void fv();typedef void fvc() const;struct S { fv memfunc1; // equivalent to: void memfunc1();void memfunc2();
fvc memfunc3; // equivalent to: void memfunc3() const;};
fv S::* pmfv1 = &S::memfunc1;
fv S::* pmfv2 = &S::memfunc2;
fvc S::* pmfv3 = &S::memfunc3; — *end example*]
— *end note*]

View File

@@ -0,0 +1,41 @@
[class.mfct.non.static]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.mfct.non.static)
### 11.4.3 Non-static member functions [class.mfct.non.static]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1121)
A non-static member function may be called for an object of
its class type, or for an object of a class derived ([[class.derived]](class.derived "11.7Derived classes"))
from its class type, using the class member
access syntax ([[expr.ref]](expr.ref "7.6.1.5Class member access"), [[over.match.call]](over.match.call "12.2.2.2Function call syntax"))[.](#1.sentence-1)
A non-static
member function may also be called directly using the function call
syntax ([[expr.call]](expr.call "7.6.1.3Function call"), [[over.match.call]](over.match.call "12.2.2.2Function call syntax")) from within
its class or a class derived from its class, or
a member thereof, as described below[.](#1.sentence-2)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1131)
[*Note [1](#note-1)*:
An implicit object member function can be declared with[*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1General[dcl.decl.general]")*s*, which affect the type of the this pointer ([[expr.prim.this]](expr.prim.this "7.5.3This")),
and/or a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6Functions"));
both affect overload resolution ([[over.match.funcs]](over.match.funcs "12.2.2Candidate functions and argument lists"))[.](#2.sentence-1)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1143)
An implicit object member function may be declared
virtual ([[class.virtual]](class.virtual "11.7.3Virtual functions")) or pure virtual ([[class.abstract]](class.abstract "11.7.4Abstract classes"))[.](#3.sentence-1)

150
cppdraft/class/mi.md Normal file
View File

@@ -0,0 +1,150 @@
[class.mi]
# 11 Classes [[class]](./#class)
## 11.7 Derived classes [[class.derived]](class.derived#class.mi)
### 11.7.2 Multiple base classes [class.mi]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3683)
A class can be derived from any number of base classes[.](#1.sentence-1)
[*Note [1](#note-1)*:
The use of more than one direct base class is often called multiple inheritance[.](#1.sentence-2)
— *end note*]
[*Example [1](#example-1)*: class A { /* ... */ };class B { /* ... */ };class C { /* ... */ };class D : public A, public B, public C { /* ... */ }; — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3697)
[*Note [2](#note-2)*:
The order of derivation is not significant except as specified by the
semantics of initialization by constructor ([[class.base.init]](class.base.init "11.9.3Initializing bases and members")),
cleanup ([[class.dtor]](class.dtor "11.4.7Destructors")), and storage
layout ([[class.mem]](class.mem "11.4Class members"), [[class.access.spec]](class.access.spec "11.8.2Access specifiers"))[.](#2.sentence-1)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3707)
A class shall not be specified as a direct base class of a derived class
more than once[.](#3.sentence-1)
[*Note [3](#note-3)*:
A class can be an indirect base class more than once and can be a direct
and an indirect base class[.](#3.sentence-2)
There are limited things that can be done
with such a class;
lookup that finds its non-static data members and member functions
in the scope of the derived class will be ambiguous[.](#3.sentence-3)
However, the static members, enumerations and types can be
unambiguously referred to[.](#3.sentence-4)
— *end note*]
[*Example [2](#example-2)*: class X { /* ... */ };class Y : public X, public X { /* ... */ }; // errorclass L { public: int next; /* ... */ };class A : public L { /* ... */ };class B : public L { /* ... */ };class C : public A, public B { void f(); /* ... */ }; // well-formedclass D : public A, public L { void f(); /* ... */ }; // well-formed — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3734)
A base class specifier that does not contain the keywordvirtual specifies a [*non-virtual base class*](#def:base_class,non-virtual "11.7.2Multiple base classes[class.mi]")[.](#4.sentence-1)
A base
class specifier that contains the keyword virtual specifies a[*virtual base class*](#def:base_class,virtual "11.7.2Multiple base classes[class.mi]")[.](#4.sentence-2)
For each distinct occurrence of a
non-virtual base class in the class lattice of the most derived class,
the most derived object ([[intro.object]](intro.object "6.8.2Object model")) shall contain a
corresponding distinct base class subobject of that type[.](#4.sentence-3)
For each
distinct base class that is specified virtual, the most derived object
shall contain a single base class subobject of that type[.](#4.sentence-4)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3746)
[*Note [4](#note-4)*:
For an object of class type C, each distinct occurrence of a
(non-virtual) base class L in the class lattice of C corresponds one-to-one with a distinct L subobject within the
object of type C[.](#5.sentence-1)
Given the class C defined above, an
object of class C will have two subobjects of class L as
shown in Figure [4](#fig:class.nonvirt)[.](#5.sentence-2)
![SVG Image](data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE0MHB0IiB3aWR0aD0iMjI0cHQiIHZpZXdCb3g9IjAuMDAgMC4wMCAyMjQuMDAgMTQwLjAwIj4KPGcgY2xhc3M9ImdyYXBoIj4Kbm9udmlydAoKPGcgY2xhc3M9Im5vZGUiPgpMMQpMCjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KTDIKTAo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+CkEKQQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkEtJmd0O0wxCjxwYXRoIGQ9Ik0yNywtNzYuNDFDMjcsLTgzLjMgMjcsLTkyLjkgMjcsLTEwMS40MyIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQgpCCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQi0mZ3Q7TDIKPHBhdGggZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgZD0iTTE4OSwtNzYuNDFDMTg5LC04My4zIDE4OSwtOTIuOSAxODksLTEwMS40MyIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQwpDCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQy0mZ3Q7QQo8cGF0aCBzdHJva2U9ImJsYWNrIiBkPSJNOTQuMjYsLTIwLjE2QzgxLjg1LC0yOC40MyA2My4zNywtNDAuNzUgNDguOTIsLTUwLjM4IiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpDLSZndDtCCjxwYXRoIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==)
Figure [4](#fig:class.nonvirt) — Non-virtual base [[fig:class.nonvirt]](./fig:class.nonvirt)
In such lattices, explicit qualification can be used to specify which
subobject is meant[.](#5.sentence-3)
The body of function C::f can refer to the
member next of each L subobject:void C::f() { A::next = B::next; } // well-formed
Without the A:: or B:: qualifiers, the definition ofC::f above would be ill-formed because of
ambiguity ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup"))[.](#5.sentence-5)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3772)
[*Note [5](#note-5)*:
In contrast, consider the case with a virtual base class:class V { /* ... */ };class A : virtual public V { /* ... */ };class B : virtual public V { /* ... */ };class C : public A, public B { /* ... */ };
![SVG Image](data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjI0cHQiIHZpZXdCb3g9IjAuMDAgMC4wMCAyMjQuMDAgMTQwLjAwIiBoZWlnaHQ9IjE0MHB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4KdmlydAoKPGcgY2xhc3M9Im5vZGUiPgpWClYKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpBCkEKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpBLSZndDtWCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik00MC43NCwtNzYuMTZDNTMuMTUsLTg0LjQzIDcxLjYzLC05Ni43NSA4Ni4wOCwtMTA2LjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpCCkIKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpCLSZndDtWCjxwYXRoIGQ9Ik0xNzUuMjYsLTc2LjE2QzE2Mi44NSwtODQuNDMgMTQ0LjM3LC05Ni43NSAxMjkuOTIsLTEwNi4zOCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSJibGFjayIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJub2RlIj4KQwpDCjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KQy0mZ3Q7QQo8cGF0aCBzdHJva2U9ImJsYWNrIiBkPSJNOTQuMjYsLTIwLjE2QzgxLjg1LC0yOC40MyA2My4zNywtNDAuNzUgNDguOTIsLTUwLjM4IiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpDLSZndDtCCjxwYXRoIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==)
Figure [5](#fig:class.virt) — Virtual base [[fig:class.virt]](./fig:class.virt)
For an object c of class type C, a single subobject of
type V is shared by every base class subobject of c that has avirtual base class of type V[.](#6.sentence-1)
Given the class C defined above, an object of class C will have one subobject of
class V, as shown in Figure [5](#fig:class.virt)[.](#6.sentence-2)
— *end note*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3795)
[*Note [6](#note-6)*:
A class can have both virtual and non-virtual base classes of a given
type[.](#7.sentence-1)
class B { /* ... */ };class X : virtual public B { /* ... */ };class Y : virtual public B { /* ... */ };class Z : public B { /* ... */ };class AA : public X, public Y, public Z { /* ... */ };
For an object of class AA, all virtual occurrences of
base class B in the class lattice of AA correspond to a
single B subobject within the object of type AA, and
every other occurrence of a (non-virtual) base class B in the
class lattice of AA corresponds one-to-one with a distinctB subobject within the object of type AA[.](#7.sentence-2)
Given the
class AA defined above, class AA has two subobjects of
class B: Z's B and the virtual B shared
by X and Y, as shown in Figure [6](#fig:class.virtnonvirt)[.](#7.sentence-3)
![SVG Image](data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjE0MHB0IiB2aWV3Qm94PSIwLjAwIDAuMDAgMzg2LjAwIDE0MC4wMCIgd2lkdGg9IjM4NnB0Ij4KPGcgY2xhc3M9ImdyYXBoIj4KdmlydG5vbnZpcnQKCjxnIGNsYXNzPSJub2RlIj4KQjEKQgo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+CkIyCkIKPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpBQQpBQQo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+ClgKWAo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkFBLSZndDtYCjxwYXRoIGQ9Ik05NC4yNiwtMjAuMTZDODEuODUsLTI4LjQzIDYzLjM3LC00MC43NSA0OC45MiwtNTAuMzgiIGZpbGw9Im5vbmUiIHN0cm9rZT0iYmxhY2siIC8+Cjxwb2x5Z29uIGZpbGw9ImJsYWNrIiBzdHJva2U9ImJsYWNrIiAvPgo8L2c+Cgo8ZyBjbGFzcz0ibm9kZSI+ClkKWQo8L2c+Cgo8ZyBjbGFzcz0iZWRnZSI+CkFBLSZndDtZCjxwYXRoIGZpbGw9Im5vbmUiIGQ9Ik0xMjEuNzQsLTIwLjE2QzEzNC4xNSwtMjguNDMgMTUyLjYzLC00MC43NSAxNjcuMDgsLTUwLjM4IiBzdHJva2U9ImJsYWNrIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9Im5vZGUiPgpaCloKPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpBQS0mZ3Q7Wgo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNMTM1LjQsLTE3LjA5QzE3OS4wOSwtMjYuOCAyNjQuNiwtNDUuOCAzMTMuNzgsLTU2LjczIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpYLSZndDtCMQo8cGF0aCBmaWxsPSJub25lIiBzdHJva2U9ImJsYWNrIiBkPSJNNDAuNzQsLTc2LjE2QzUzLjE1LC04NC40MyA3MS42MywtOTYuNzUgODYuMDgsLTEwNi4zOCIgLz4KPHBvbHlnb24gZmlsbD0iYmxhY2siIHN0cm9rZT0iYmxhY2siIC8+CjwvZz4KCjxnIGNsYXNzPSJlZGdlIj4KWS0mZ3Q7QjEKPHBhdGggc3Ryb2tlPSJibGFjayIgZD0iTTE3NS4yNiwtNzYuMTZDMTYyLjg1LC04NC40MyAxNDQuMzcsLTk2Ljc1IDEyOS45MiwtMTA2LjM4IiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgoKPGcgY2xhc3M9ImVkZ2UiPgpaLSZndDtCMgo8cGF0aCBzdHJva2U9ImJsYWNrIiBkPSJNMzUxLC03Ni40MUMzNTEsLTgzLjMgMzUxLC05Mi45IDM1MSwtMTAxLjQzIiBmaWxsPSJub25lIiAvPgo8cG9seWdvbiBmaWxsPSJibGFjayIgc3Ryb2tlPSJibGFjayIgLz4KPC9nPgo8L2c+Cjwvc3ZnPg==)
Figure [6](#fig:class.virtnonvirt) — Virtual and non-virtual base [[fig:class.virtnonvirt]](./fig:class.virtnonvirt)
— *end note*]

108
cppdraft/class/name.md Normal file
View File

@@ -0,0 +1,108 @@
[class.name]
# 11 Classes [[class]](./#class)
## 11.3 Class names [class.name]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L408)
A class definition introduces a new type[.](#1.sentence-1)
[*Example [1](#example-1)*:
struct X { int a; };struct Y { int a; };
X a1;
Y a2;int a3; declares three variables of three different types[.](#1.sentence-2)
This implies thata1 = a2; // error: Y assigned to X a1 = a3; // error: int assigned to X are type mismatches, and thatint f(X);int f(Y);declare overloads ([[over]](over "12Overloading")) named f and not
simply a single function f twice[.](#1.sentence-3)
For the same reason,struct S { int a; };struct S { int a; }; // error: double definition is ill-formed because it defines S twice[.](#1.sentence-4)
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L438)
[*Note [1](#note-1)*:
It can be necessary to use an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") to refer to a class
that belongs to a scope in which its name is also bound to
a variable, function, or enumerator ([[basic.lookup.elab]](basic.lookup.elab "6.5.6Elaborated type specifiers"))[.](#2.sentence-1)
[*Example [2](#example-2)*: struct stat {// ...};
stat gstat; // use plain stat to define variableint stat(struct stat*); // stat now also names a functionvoid f() {struct stat* ps; // struct prefix needed to name struct stat stat(ps); // call stat function} — *end example*]
An [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") can also be used to declare
an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") as a [*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]")[.](#2.sentence-2)
[*Example [3](#example-3)*: struct s { int a; };
void g() {struct s; // hide global struct s with a block-scope declaration s* p; // refer to local struct sstruct s { char* p; }; // define local struct sstruct s; // redeclaration, has no effect} — *end example*]
Such declarations allow definition of classes that refer to each other[.](#2.sentence-3)
[*Example [4](#example-4)*: class Vector;
class Matrix {// ...friend Vector operator*(const Matrix&, const Vector&);};
class Vector {// ...friend Vector operator*(const Matrix&, const Vector&);};
Declaration of friends is described in [[class.friend]](class.friend "11.8.4Friends"),
operator functions in [[over.oper]](over.oper "12.4Overloaded operators")[.](#2.sentence-4)
— *end example*]
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L497)
[*Note [2](#note-2)*:
An [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers")) can also
be used as a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1General[dcl.type.general]") as part of a declaration[.](#3.sentence-1)
It
differs from a class declaration in that it can refer to
an existing class of the given name[.](#3.sentence-2)
— *end note*]
[*Example [5](#example-5)*: struct s { int a; };
void g(int s) {struct s* p = new struct s; // global s p->a = s; // parameter s} — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L517)
[*Note [3](#note-3)*:
The declaration of a class name takes effect immediately after the[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]") is seen in the class definition or[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]")[.](#4.sentence-1)
[*Example [6](#example-6)*:
class A * A; first specifies A to be the name of a class and then redefines
it as the name of a pointer to an object of that class[.](#4.sentence-2)
This means that
the elaborated form class A must be used to refer to the
class[.](#4.sentence-3)
Such artistry with names can be confusing and is best avoided[.](#4.sentence-4)
— *end example*]
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L534)
A [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") is only a [*class-name*](class.pre#nt:class-name "11.1Preamble[class.pre]") if its [*template-name*](temp.names#nt:template-name "13.3Names of template specializations[temp.names]") names a class template[.](#5.sentence-1)

56
cppdraft/class/nest.md Normal file
View File

@@ -0,0 +1,56 @@
[class.nest]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.nest)
### 11.4.12 Nested class declarations [class.nest]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3111)
A class can be declared within another class[.](#1.sentence-1)
A class declared within
another is called a [*nested class*](#def:class,nested "11.4.12Nested class declarations[class.nest]")[.](#1.sentence-2)
[*Note [1](#note-1)*:
See [[expr.prim.id]](expr.prim.id "7.5.5Names") for restrictions on the use of non-static data
members and non-static member functions[.](#1.sentence-3)
— *end note*]
[*Example [1](#example-1)*: int x;int y;
struct enclose {int x; static int s; struct inner {void f(int i) {int a = sizeof(x); // OK, operand of sizeof is an unevaluated operand x = i; // error: assign to enclose::x s = i; // OK, assign to enclose::s::x = i; // OK, assign to global x y = i; // OK, assign to global y}void g(enclose* p, int i) { p->x = i; // OK, assign to enclose::x}};};
inner* p = 0; // error: inner not found — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3146)
[*Note [2](#note-2)*:
Nested classes can be defined
either in the enclosing class or in an enclosing namespace;
member functions and static data members of a nested class can be
defined either in the nested class or in an enclosing namespace scope[.](#2.sentence-1)
[*Example [2](#example-2)*: struct enclose {struct inner {static int x; void f(int i); };};
int enclose::inner::x = 1;
void enclose::inner::f(int i) { /* ... */ }class E {class I1; // forward declaration of nested classclass I2; class I1 { }; // definition of nested class};class E::I2 { }; // definition of nested class — *end example*]
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3175)
A friend function ([[class.friend]](class.friend "11.8.4Friends")) defined
within a nested class has no special access rights to
members of an enclosing class[.](#3.sentence-1)

21
cppdraft/class/paths.md Normal file
View File

@@ -0,0 +1,21 @@
[class.paths]
# 11 Classes [[class]](./#class)
## 11.8 Member access control [[class.access]](class.access#class.paths)
### 11.8.7 Multiple access [class.paths]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5284)
If a declaration can be reached by several paths through a multiple inheritance
graph, the access is that of the path that gives most access[.](#1.sentence-1)
[*Example [1](#example-1)*: class W { public: void f(); };class A : private virtual W { };class B : public virtual W { };class C : public A, public B {void f() { W::f(); } // OK};
SinceW::f() is available toC::f() along the public path throughB,
access is allowed[.](#1.sentence-2)
— *end example*]

163
cppdraft/class/pre.md Normal file
View File

@@ -0,0 +1,163 @@
[class.pre]
# 11 Classes [[class]](./#class)
## 11.1 Preamble [class.pre]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L11)
A class is a type[.](#1.sentence-1)
Its name becomes a [*class-name*](#nt:class-name "11.1Preamble[class.pre]") ([[class.name]](class.name "11.3Class names")) within its
scope[.](#1.sentence-2)
[class-name:](#nt:class-name "11.1Preamble[class.pre]")
[*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]")
[*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]")
A [*class-specifier*](#nt:class-specifier "11.1Preamble[class.pre]") or
an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5Elaborated type specifiers")) is used to
make a [*class-name*](#nt:class-name "11.1Preamble[class.pre]")[.](#1.sentence-3)
An object of a class consists of a
(possibly empty) sequence of members and base class objects[.](#1.sentence-4)
[class-specifier:](#nt:class-specifier "11.1Preamble[class.pre]")
[*class-head*](#nt:class-head "11.1Preamble[class.pre]") { [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]")opt }
[class-head:](#nt:class-head "11.1Preamble[class.pre]")
[*class-key*](#nt:class-key "11.1Preamble[class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*class-head-name*](#nt:class-head-name "11.1Preamble[class.pre]") [*class-property-specifier-seq*](#nt:class-property-specifier-seq "11.1Preamble[class.pre]")opt [*base-clause*](class.derived.general#nt:base-clause "11.7.1General[class.derived.general]")opt
[*class-key*](#nt:class-key "11.1Preamble[class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*base-clause*](class.derived.general#nt:base-clause "11.7.1General[class.derived.general]")opt
[class-head-name:](#nt:class-head-name "11.1Preamble[class.pre]")
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]")opt [*class-name*](#nt:class-name "11.1Preamble[class.pre]")
[class-property-specifier-seq:](#nt:class-property-specifier-seq "11.1Preamble[class.pre]")
[*class-property-specifier*](#nt:class-property-specifier "11.1Preamble[class.pre]") [*class-property-specifier-seq*](#nt:class-property-specifier-seq "11.1Preamble[class.pre]")opt
[class-property-specifier:](#nt:class-property-specifier "11.1Preamble[class.pre]")
final
trivially_relocatable_if_eligible
replaceable_if_eligible
[class-key:](#nt:class-key "11.1Preamble[class.pre]")
class
struct
union
A class declaration where the [*class-name*](#nt:class-name "11.1Preamble[class.pre]") in the [*class-head-name*](#nt:class-head-name "11.1Preamble[class.pre]") is a [*simple-template-id*](temp.names#nt:simple-template-id "13.3Names of template specializations[temp.names]") shall be an explicit specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4Explicit specialization")) or
a partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6Partial specialization"))[.](#1.sentence-5)
A [*class-specifier*](#nt:class-specifier "11.1Preamble[class.pre]") whose[*class-head*](#nt:class-head "11.1Preamble[class.pre]") omits the[*class-head-name*](#nt:class-head-name "11.1Preamble[class.pre]") defines an [*unnamed class*](#def:class,unnamed "11.1Preamble[class.pre]")[.](#1.sentence-6)
[*Note [1](#note-1)*:
An unnamed class thus can't
be final[.](#1.sentence-7)
— *end note*]
Otherwise, the [*class-name*](#nt:class-name "11.1Preamble[class.pre]") is an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]");
it is not looked up, and the [*class-specifier*](#nt:class-specifier "11.1Preamble[class.pre]") introduces it[.](#1.sentence-8)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L81)
The component name of the[*class-name*](#nt:class-name "11.1Preamble[class.pre]") is also bound in the scope of the class (template)
itself; this is known as the [*injected-class-name*](#def:injected-class-name "11.1Preamble[class.pre]")[.](#2.sentence-1)
For purposes of access checking, the injected-class-name is treated as
if it were a public member name[.](#2.sentence-2)
A [*class-specifier*](#nt:class-specifier "11.1Preamble[class.pre]") is commonly referred to as a [*class
definition*](#def:definition,class "11.1Preamble[class.pre]")[.](#2.sentence-3)
A class is considered defined after the closing brace of its[*class-specifier*](#nt:class-specifier "11.1Preamble[class.pre]") has been seen even though its member
functions are in general not yet defined[.](#2.sentence-4)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") appertains to the class; the attributes in
the [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") are thereafter considered attributes of the class
whenever it is named[.](#2.sentence-5)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L97)
If a [*class-head-name*](#nt:class-head-name "11.1Preamble[class.pre]") contains a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"),
the [*class-specifier*](#nt:class-specifier "11.1Preamble[class.pre]") shall not inhabit a class scope[.](#3.sentence-1)
If its [*class-name*](#nt:class-name "11.1Preamble[class.pre]") is an [*identifier*](lex.name#nt:identifier "5.11Identifiers[lex.name]"),
the [*class-specifier*](#nt:class-specifier "11.1Preamble[class.pre]") shall correspond to
one or more declarations nominable in
the class, class template, or namespace to which the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") refers;
they shall all have the same target scope, and the target scope of the[*class-specifier*](#nt:class-specifier "11.1Preamble[class.pre]") is that scope[.](#3.sentence-2)
[*Example [1](#example-1)*: namespace N {template<class>struct A {struct B; };}using N::A;template<class T> struct A<T>::B {}; // OKtemplate<> struct A<void> {}; // OK — *end example*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L121)
[*Note [2](#note-2)*:
The [*class-key*](#nt:class-key "11.1Preamble[class.pre]") determines
whether the class is a union ([[class.union]](class.union "11.5Unions")) and
whether access is public or private by default ([[class.access]](class.access "11.8Member access control"))[.](#4.sentence-1)
A union holds the value of at most one data member at a time[.](#4.sentence-2)
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L129)
Each [*class-property-specifier*](#nt:class-property-specifier "11.1Preamble[class.pre]") shall appear at most once
within a single [*class-property-specifier-seq*](#nt:class-property-specifier-seq "11.1Preamble[class.pre]")[.](#5.sentence-1)
Whenever a [*class-key*](#nt:class-key "11.1Preamble[class.pre]") is followed
by a [*class-head-name*](#nt:class-head-name "11.1Preamble[class.pre]"),
one of the identifiers final, trivially_relocatable_if_eligible,
or replaceable_if_eligible, and a colon or left brace,
the identifier is interpreted as a [*class-property-specifier*](#nt:class-property-specifier "11.1Preamble[class.pre]")[.](#5.sentence-2)
[*Example [2](#example-2)*: struct A;struct A final {}; // OK, definition of struct A,// not value-initialization of variable finalstruct X {struct C { constexpr operator int() { return 5; } }; struct B trivially_relocatable_if_eligible : C{}; // OK, definition of nested class B,// not declaration of a bit-field member// trivially_relocatable_if_eligible}; — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L153)
If a class is marked with the [*class-property-specifier*](#nt:class-property-specifier "11.1Preamble[class.pre]")final and that class appears as a [*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1General[class.derived.general]") in a [*base-clause*](class.derived.general#nt:base-clause "11.7.1General[class.derived.general]") ([[class.derived]](class.derived "11.7Derived classes")), the program is ill-formed[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L158)
[*Note [3](#note-3)*:
Complete objects of class type have nonzero size[.](#7.sentence-1)
Base class subobjects and
members declared with the no_unique_address attribute ([[dcl.attr.nouniqueaddr]](dcl.attr.nouniqueaddr "9.13.11No unique address attribute"))
are not so constrained[.](#7.sentence-2)
— *end note*]
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L166)
[*Note [4](#note-4)*:
Class objects can be assigned ([[over.assign]](over.assign "12.4.3.2Simple assignment"), [[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator")),
passed as arguments to functions ([[dcl.init]](dcl.init "9.5Initializers"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")), and
returned by functions (except objects of classes for which copying or moving has
been restricted; see [[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3Deleted definitions") and [[class.access]](class.access "11.8Member access control"))[.](#8.sentence-1)
Other plausible operators, such as equality comparison,
can be defined by the user; see [[over.oper]](over.oper "12.4Overloaded operators")[.](#8.sentence-2)
— *end note*]

315
cppdraft/class/prop.md Normal file
View File

@@ -0,0 +1,315 @@
[class.prop]
# 11 Classes [[class]](./#class)
## 11.2 Properties of classes [class.prop]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L178)
A [*trivially copyable class*](#def:class,trivially_copyable "11.2Properties of classes[class.prop]") is a class:
- [(1.1)](#1.1)
that has at least one eligible
copy constructor, move constructor,
copy assignment operator, or
move assignment operator ([[special]](special "11.4.4Special member functions"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors"), [[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator")),
- [(1.2)](#1.2)
where each eligible copy constructor, move constructor, copy assignment operator,
and move assignment operator is trivial, and
- [(1.3)](#1.3)
that has a trivial, non-deleted destructor ([[class.dtor]](class.dtor "11.4.7Destructors"))[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L190)
A class C is [*default-movable*](#def:default-movable "11.2Properties of classes[class.prop]") if
- [(2.1)](#2.1)
overload resolution for direct-initializing an object of type C from an xvalue of type C selects a constructor that is a direct member
of C and is neither user-provided nor deleted,
- [(2.2)](#2.2)
overload resolution for assigning to an lvalue of type C from an
xvalue of type C selects an assignment operator function that is a
direct member of C and is neither user-provided nor deleted, and
- [(2.3)](#2.3)
C has a destructor that is neither user-provided nor deleted.
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L205)
A class is [*eligible for trivial relocation*](#def:eligible_for_trivial_relocation "11.2Properties of classes[class.prop]") unless it
- [(3.1)](#3.1)
has any virtual base classes,
- [(3.2)](#3.2)
has a base class that is not a trivially relocatable class,
- [(3.3)](#3.3)
has a non-static data member of an object type that is not of a
trivially relocatable type, or
- [(3.4)](#3.4)
has a deleted destructor,
except that it is implementation-defined
whether an otherwise-eligible union having one or more subobjects of
polymorphic class type is eligible for trivial relocation[.](#3.sentence-1)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L220)
A class C is a [*trivially relocatable class*](#def:class,trivially_relocatable "11.2Properties of classes[class.prop]") if it is eligible for trivial relocation and
- [(4.1)](#4.1)
has the trivially_relocatable_if_eligible [*class-property-specifier*](class.pre#nt:class-property-specifier "11.1Preamble[class.pre]"),
- [(4.2)](#4.2)
is a union with no user-declared special member functions, or
- [(4.3)](#4.3)
is default-movable[.](#4.sentence-1)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L229)
[*Note [1](#note-1)*:
A class with const-qualified or reference non-static data members can be
trivially relocatable[.](#5.sentence-1)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L235)
A class C is [*eligible for replacement*](#def:eligible_for_replacement "11.2Properties of classes[class.prop]") unless
- [(6.1)](#6.1)
it has a base class that is not a replaceable class,
- [(6.2)](#6.2)
it has a non-static data member that is not of a replaceable type,
- [(6.3)](#6.3)
overload resolution fails or selects a deleted constructor when
direct-initializing an object of type C from an xvalue of typeC ([[dcl.init.general]](dcl.init.general "9.5.1General")),
- [(6.4)](#6.4)
overload resolution fails or selects a deleted assignment operator
function when assigning to an lvalue of type C from an xvalue of typeC ([[expr.assign]](expr.assign "7.6.19Assignment and compound assignment operators"), [[over.assign]](over.assign "12.4.3.2Simple assignment")), or
- [(6.5)](#6.5)
it has a deleted destructor[.](#6.sentence-1)
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L252)
A class C is a [*replaceable class*](#def:class,replaceable "11.2Properties of classes[class.prop]") if it is
eligible for replacement and
- [(7.1)](#7.1)
has the replaceable_if_eligible [*class-property-specifier*](class.pre#nt:class-property-specifier "11.1Preamble[class.pre]"),
- [(7.2)](#7.2)
is a union with no user-declared special member functions, or
- [(7.3)](#7.3)
is default-movable[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L261)
[*Note [2](#note-2)*:
Accessibility of the special member functions is not considered when
establishing trivial relocatability or replaceability[.](#8.sentence-1)
— *end note*]
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L267)
[*Note [3](#note-3)*:
Not all trivially copyable classes are trivially relocatable or replaceable[.](#9.sentence-1)
— *end note*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L272)
A class S is a [*standard-layout class*](#def:class,standard-layout "11.2Properties of classes[class.prop]") if it:
- [(10.1)](#10.1)
has no non-static data members of type non-standard-layout class
(or array of such types) or reference,
- [(10.2)](#10.2)
has no [virtual functions](class.virtual "11.7.3Virtual functions[class.virtual]") and no[virtual base classes](class.mi "11.7.2Multiple base classes[class.mi]"),
- [(10.3)](#10.3)
has the same [access control](class.access "11.8Member access control[class.access]") for all non-static data members,
- [(10.4)](#10.4)
has no non-standard-layout base classes,
- [(10.5)](#10.5)
has at most one base class subobject of any given type,
- [(10.6)](#10.6)
has all non-static data members and bit-fields in the class and
its base classes first declared in the same class, and
- [(10.7)](#10.7)
has no element of the set M(S) of types
as a base class,
where for any type X, M(X) is defined as follows[.](#10.sentence-1)[88](#footnote-88 "This ensures that two subobjects that have the same class type and that belong to the same most derived object are not allocated at the same address ([expr.eq]).")
[*Note [4](#note-4)*:
M(X) is the set of the types of all non-base-class subobjects
that can be at a zero offset in X[.](#10.7.sentence-2)
— *end note*]
* [(10.7.1)](#10.7.1)
If X is a non-union class type with no non-static data members,
the set M(X) is empty[.](#10.7.1.sentence-1)
* [(10.7.2)](#10.7.2)
If X is a non-union class type with a non-static data
member of type X0 that is either of zero size or
is the first non-static data member of X (where said member may be an anonymous union),
the set M(X) consists of X0 and the elements ofM(X0)[.](#10.7.2.sentence-1)
* [(10.7.3)](#10.7.3)
If X is a union type, the set M(X) is
the union of all M(Ui) and the set containing all Ui,
where each Ui is the type of the ith non-static data member
of X[.](#10.7.3.sentence-1)
* [(10.7.4)](#10.7.4)
If X is an array type with element type Xe,
the set M(X) consists of Xe and the elements of M(Xe)[.](#10.7.4.sentence-1)
* [(10.7.5)](#10.7.5)
If X is a non-class, non-array type, the set M(X) is empty[.](#10.7.5.sentence-1)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L330)
[*Example [1](#example-1)*: struct B { int i; }; // standard-layout classstruct C : B { }; // standard-layout classstruct D : C { }; // standard-layout classstruct E : D { char : 4; }; // not a standard-layout classstruct Q {};struct S : Q { };struct T : Q { };struct U : S, T { }; // not a standard-layout class — *end example*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L345)
A [*standard-layout struct*](#def:struct,standard-layout "11.2Properties of classes[class.prop]") is a standard-layout class
defined with the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") struct or the[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") class[.](#12.sentence-1)
A [*standard-layout union*](#def:union,standard-layout "11.2Properties of classes[class.prop]") is a standard-layout class
defined with the[*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]") union[.](#12.sentence-2)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L353)
[*Note [5](#note-5)*:
Standard-layout classes are useful for communicating with
code written in other programming languages[.](#13.sentence-1)
Their layout is specified
in [[class.mem.general]](class.mem.general "11.4.1General") and [[expr.rel]](expr.rel "7.6.9Relational operators")[.](#13.sentence-2)
— *end note*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L360)
[*Example [2](#example-2)*: struct N { // neither trivially copyable nor standard-layoutint i; int j; virtual ~N();};
struct T { // trivially copyable but not standard-layoutint i;private:int j;};
struct SL { // standard-layout but not trivially copyableint i; int j; ~SL();};
struct POD { // both trivially copyable and standard-layoutint i; int j;}; — *end example*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L388)
[*Note [6](#note-6)*:
Aggregates of class type are described in [[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates")[.](#15.sentence-1)
— *end note*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L393)
A class S is an [*implicit-lifetime class*](#def:class,implicit-lifetime "11.2Properties of classes[class.prop]") if
- [(16.1)](#16.1)
it is an aggregate whose destructor is not user-provided or
- [(16.2)](#16.2)
it has at least one trivial eligible constructor and
a trivial, non-deleted destructor[.](#16.sentence-1)
[88)](#footnote-88)[88)](#footnoteref-88)
This ensures that two subobjects that have the same class type and that
belong to the same most derived object are not allocated at the same
address ([[expr.eq]](expr.eq "7.6.10Equality operators"))[.](#footnote-88.sentence-1)

View File

@@ -0,0 +1,39 @@
[class.protected]
# 11 Classes [[class]](./#class)
## 11.8 Member access control [[class.access]](class.access#class.protected)
### 11.8.5 Protected member access [class.protected]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L5181)
An additional access check beyond those described earlier in [[class.access]](class.access "11.8Member access control") is applied when a non-static data member or non-static member function is a
protected member of its naming class ([[class.access.base]](class.access.base "11.8.3Accessibility of base classes and base class members"))[.](#1.sentence-1)[98](#footnote-98 "This additional check does not apply to other members, e.g., static data members or enumerator member constants.")
As described earlier, access to a protected member is granted because the
reference occurs in a friend or direct member of some class C[.](#1.sentence-2)
If the access is
to form a pointer to member ([[expr.unary.op]](expr.unary.op "7.6.2.2Unary operators")), the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]") shall denote C or a class derived fromC[.](#1.sentence-3)
All other accesses involve a (possibly implicit) object
expression ([[expr.ref]](expr.ref "7.6.1.5Class member access"))[.](#1.sentence-4)
In this case, the class of the object expression shall beC or a class derived from C[.](#1.sentence-5)
[*Example [1](#example-1)*: class B {protected:int i; static int j;};
class D1 : public B {};
class D2 : public B {friend void fr(B*,D1*,D2*); void mem(B*,D1*);};
void fr(B* pb, D1* p1, D2* p2) { pb->i = 1; // error p1->i = 2; // error p2->i = 3; // OK (access through a D2) p2->B::i = 4; // OK (access through a D2, even though naming class is B)int B::* pmi_B = &B::i; // errorint B::* pmi_B2 = &D2::i; // OK (type of &D2::i is int B::*) B::j = 5; // error: not a friend of naming class B D2::j = 6; // OK (because refers to static member)}void D2::mem(B* pb, D1* p1) { pb->i = 1; // error p1->i = 2; // error i = 3; // OK (access through this) B::i = 4; // OK (access through this, qualification ignored)int B::* pmi_B = &B::i; // errorint B::* pmi_B2 = &D2::i; // OK j = 5; // OK (because j refers to static member) B::j = 6; // OK (because B::j refers to static member)}void g(B* pb, D1* p1, D2* p2) { pb->i = 1; // error p1->i = 2; // error p2->i = 3; // error} — *end example*]
[98)](#footnote-98)[98)](#footnoteref-98)
This
additional check does not apply to other members,
e.g., static data members or enumerator member constants[.](#footnote-98.sentence-1)

40
cppdraft/class/qual.md Normal file
View File

@@ -0,0 +1,40 @@
[class.qual]
# 6 Basics [[basic]](./#basic)
## 6.5 Name lookup [[basic.lookup]](basic.lookup#class.qual)
### 6.5.5 Qualified name lookup [[basic.lookup.qual]](basic.lookup.qual#class.qual)
#### 6.5.5.2 Class members [class.qual]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L2537)
In a lookup for a qualified name N whose lookup context is a class C in which function names are not ignored,[18](#footnote-18 "Lookups in which function names are ignored include names appearing in a nested-name-specifier, an elaborated-type-specifier, or a base-specifier.")
- [(1.1)](#1.1)
if the search finds the injected-class-name of C ([[class.pre]](class.pre "11.1Preamble")), or
- [(1.2)](#1.2)
if N is dependent and
is the terminal name of a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10The using declaration[namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10The using declaration"))
that names a constructor,
N is instead considered to name the constructor of class C[.](#1.sentence-1)
Such a constructor name shall be used only
in the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1General[dcl.decl.general]") of a (friend) declaration of a constructor or
in a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10The using declaration[namespace.udecl]")[.](#1.sentence-2)
[*Example [1](#example-1)*: struct A { A(); };struct B: public A { B(); };
A::A() { } B::B() { } B::A ba; // object of type A A::A a; // error: A::A is not a type namestruct A::A a2; // object of type A — *end example*]
[18)](#footnote-18)[18)](#footnoteref-18)
Lookups in which
function names are ignored include names appearing in a[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3Qualified names[expr.prim.id.qual]"), an[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5Elaborated type specifiers[dcl.type.elab]"), or a [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1General[class.derived.general]")[.](#footnote-18.sentence-1)

105
cppdraft/class/slice.md Normal file
View File

@@ -0,0 +1,105 @@
[class.slice]
# 29 Numerics library [[numerics]](./#numerics)
## 29.6 Numeric arrays [[numarray]](numarray#class.slice)
### 29.6.4 Class slice [class.slice]
#### [29.6.4.1](#overview) Overview [[class.slice.overview]](class.slice.overview)
[🔗](#lib:slice)
namespace std {class slice {public: slice();
slice(size_t, size_t, size_t);
slice(const slice&);
size_t start() const;
size_t size() const;
size_t stride() const; friend bool operator==(const slice& x, const slice& y); };}
[1](#overview-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8393)
The slice class represents a BLAS-like slice from an array[.](#overview-1.sentence-1)
Such a slice is specified by a starting index, a length, and a
stride[.](#overview-1.sentence-2)[252](#footnote-252 "BLAS stands for Basic Linear Algebra Subprograms. C++ programs can instantiate this class. See, for example, Dongarra, Du Croz, Duff, and Hammerling: A set of Level 3 Basic Linear Algebra Subprograms; Technical Report MCS-P1-0888, Argonne National Laboratory (USA), Mathematics and Computer Science Division, August, 1988.")
[252)](#footnote-252)[252)](#footnoteref-252)
BLAS stands for*Basic Linear Algebra Subprograms*[.](#footnote-252.sentence-1)
C++ programs can instantiate this class[.](#footnote-252.sentence-2)
See, for example,
Dongarra, Du Croz, Duff, and Hammerling:*A set of Level 3 Basic Linear Algebra Subprograms*;
Technical Report MCS-P1-0888,
Argonne National Laboratory (USA),
Mathematics and Computer Science Division,
August, 1988[.](#footnote-252.sentence-3)
#### [29.6.4.2](#cons.slice) Constructors [[cons.slice]](cons.slice)
[🔗](#lib:slice,constructor)
`slice();
slice(size_t start, size_t length, size_t stride);
`
[1](#cons.slice-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8420)
The default constructor is equivalent to slice(0, 0, 0)[.](#cons.slice-1.sentence-1)
A default constructor is provided only to permit the declaration of arrays of slices[.](#cons.slice-1.sentence-2)
The constructor with arguments for a slice takes a start, length, and stride
parameter[.](#cons.slice-1.sentence-3)
[2](#cons.slice-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8426)
[*Example [1](#cons.slice-example-1)*:
slice(3, 8, 2) constructs a slice which selects elements 3,5,7,…,17 from an array[.](#cons.slice-2.sentence-1)
— *end example*]
#### [29.6.4.3](#slice.access) Access functions [[slice.access]](slice.access)
[🔗](#lib:start,slice)
`size_t start() const;
size_t size() const;
size_t stride() const;
`
[1](#slice.access-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8444)
*Returns*: The start, length, or stride specified
by a slice object[.](#slice.access-1.sentence-1)
[2](#slice.access-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8449)
*Complexity*: Constant time[.](#slice.access-2.sentence-1)
#### [29.6.4.4](#slice.ops) Operators [[slice.ops]](slice.ops)
[🔗](#lib:stride,slice_)
`friend bool operator==(const slice& x, const slice& y);
`
[1](#slice.ops-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8462)
*Effects*: Equivalent to:return x.start() == y.start() && x.size() == y.size() && x.stride() == y.stride();

View File

@@ -0,0 +1,41 @@
[class.slice.overview]
# 29 Numerics library [[numerics]](./#numerics)
## 29.6 Numeric arrays [[numarray]](numarray#class.slice.overview)
### 29.6.4 Class slice [[class.slice]](class.slice#overview)
#### 29.6.4.1 Overview [class.slice.overview]
[🔗](#lib:slice)
namespace std {class slice {public: slice();
slice(size_t, size_t, size_t);
slice(const slice&);
size_t start() const;
size_t size() const;
size_t stride() const; friend bool operator==(const slice& x, const slice& y); };}
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/numerics.tex#L8393)
The slice class represents a BLAS-like slice from an array[.](#1.sentence-1)
Such a slice is specified by a starting index, a length, and a
stride[.](#1.sentence-2)[252](#footnote-252 "BLAS stands for Basic Linear Algebra Subprograms. C++ programs can instantiate this class. See, for example, Dongarra, Du Croz, Duff, and Hammerling: A set of Level 3 Basic Linear Algebra Subprograms; Technical Report MCS-P1-0888, Argonne National Laboratory (USA), Mathematics and Computer Science Division, August, 1988.")
[252)](#footnote-252)[252)](#footnoteref-252)
BLAS stands for*Basic Linear Algebra Subprograms*[.](#footnote-252.sentence-1)
C++ programs can instantiate this class[.](#footnote-252.sentence-2)
See, for example,
Dongarra, Du Croz, Duff, and Hammerling:*A set of Level 3 Basic Linear Algebra Subprograms*;
Technical Report MCS-P1-0888,
Argonne National Laboratory (USA),
Mathematics and Computer Science Division,
August, 1988[.](#footnote-252.sentence-3)

115
cppdraft/class/spaceship.md Normal file
View File

@@ -0,0 +1,115 @@
[class.spaceship]
# 11 Classes [[class]](./#class)
## 11.10 Comparisons [[class.compare]](class.compare#class.spaceship)
### 11.10.3 Three-way comparison [class.spaceship]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6731)
The [*synthesized three-way comparison*](#def:three-way_comparison,synthesized "11.10.3Three-way comparison[class.spaceship]") of type R ([[cmp.categories]](cmp.categories "17.12.2Comparison category types"))
of glvalues a and b of the same type
is defined as follows:
- [(1.1)](#1.1)
If a <=> b is usable ([[class.compare.default]](class.compare.default "11.10.1Defaulted comparison operator functions")) and
can be explicitly converted to R using static_cast,static_cast<R>(a <=> b)[.](#1.1.sentence-1)
- [(1.2)](#1.2)
Otherwise, if a <=> b is usable or
overload resolution for a <=> b is performed and
finds at least one viable candidate,
the synthesized three-way comparison is not defined[.](#1.2.sentence-1)
- [(1.3)](#1.3)
Otherwise, if R is not a comparison category type, or either
the expression a == b or the expression a < b is not usable,
the synthesized three-way comparison is not defined[.](#1.3.sentence-1)
- [(1.4)](#1.4)
Otherwise, if R is strong_ordering, thena == b ? strong_ordering::equal : a < b ? strong_ordering::less : strong_ordering::greater
- [(1.5)](#1.5)
Otherwise, if R is weak_ordering, thena == b ? weak_ordering::equivalent : a < b ? weak_ordering::less : weak_ordering::greater
- [(1.6)](#1.6)
Otherwise (when R is partial_ordering),a == b ? partial_ordering::equivalent : a < b ? partial_ordering::less : b < a ? partial_ordering::greater : partial_ordering::unordered
[*Note [1](#note-1)*:
A synthesized three-way comparison is ill-formed
if overload resolution finds usable candidates
that do not otherwise meet the requirements implied by the defined expression[.](#1.sentence-2)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6786)
Let R be the declared return type of
a defaulted three-way comparison operator function, and
let xi be the elements of
the expanded list of subobjects for
an object x of type C[.](#2.sentence-1)
- [(2.1)](#2.1)
If R is auto, then
let cvi Ri be
the type of the expression xi <=> xi[.](#2.1.sentence-1)
The operator function is defined as deleted
if that expression is not usable or
if Ri is not
a comparison category type ([[cmp.categories.pre]](cmp.categories.pre "17.12.2.1Preamble")) for any i[.](#2.1.sentence-2)
The return type is deduced as
the common comparison type (see below) ofR0, R1, …, Rn−1[.](#2.1.sentence-3)
- [(2.2)](#2.2)
Otherwise, R shall not contain a placeholder type[.](#2.2.sentence-1)
If the synthesized three-way comparison of type R between any objects xi and xi is not defined,
the operator function is defined as deleted[.](#2.2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6813)
The return value of type R of the defaulted three-way comparison operator function
with parameters x and y of the same type
is determined by comparing corresponding elementsxi and yi in the expanded lists of subobjects for x and y (in increasing index order)
until the first index i where
the synthesized three-way comparison of type R between xi and yi yields a result value vi where vi!=0,
contextually converted to bool, yields true[.](#3.sentence-1)
The return value is a copy of vi if such an index exists andstatic_cast<R>(std::strong_ordering::equal) otherwise[.](#3.sentence-2)
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L6830)
The [*common comparison type*](#def:common_comparison_type "11.10.3Three-way comparison[class.spaceship]") U of a possibly-empty list of n comparison category typesT0, T1, …, Tn−1 is defined as follows:
- [(4.1)](#4.1)
If at least one Ti is std::partial_ordering,U is std::partial_ordering ([[cmp.partialord]](cmp.partialord "17.12.2.2Class partial_­ordering"))[.](#4.1.sentence-1)
- [(4.2)](#4.2)
Otherwise, if at least one Ti is std::weak_ordering,U is std::weak_ordering ([[cmp.weakord]](cmp.weakord "17.12.2.3Class weak_­ordering"))[.](#4.2.sentence-1)
- [(4.3)](#4.3)
Otherwise, U is std::strong_ordering ([[cmp.strongord]](cmp.strongord "17.12.2.4Class strong_­ordering"))[.](#4.3.sentence-1)
[*Note [2](#note-2)*:
In particular, this is the result when n is 0[.](#4.3.sentence-2)
— *end note*]

182
cppdraft/class/static.md Normal file
View File

@@ -0,0 +1,182 @@
[class.static]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.static)
### 11.4.9 Static members [class.static]
#### [11.4.9.1](#general) General [[class.static.general]](class.static.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2732)
A static member s of class X may be referred to
using the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") expression X::s; it is not
necessary to use the class member access syntax ([[expr.ref]](expr.ref "7.6.1.5Class member access")) to
refer to a static member[.](#general-1.sentence-1)
A static member may be
referred to using the class member access syntax, in which case the
object expression is evaluated[.](#general-1.sentence-2)
[*Example [1](#general-example-1)*: struct process {static void reschedule();};
process& g();
void f() { process::reschedule(); // OK, no object necessary g().reschedule(); // g() is called} — *end example*]
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2753)
Static members obey the usual class member access rules ([[class.access]](class.access "11.8Member access control"))[.](#general-2.sentence-1)
When used in the declaration of a class
member, the static specifier shall only be used in the member
declarations that appear within the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of
the class definition[.](#general-2.sentence-2)
[*Note [1](#general-note-1)*:
It cannot be specified in member declarations that appear in namespace scope[.](#general-2.sentence-3)
— *end note*]
#### [11.4.9.2](#mfct) Static member functions [[class.static.mfct]](class.static.mfct)
[1](#mfct-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2766)
[*Note [1](#mfct-note-1)*:
The rules described in [[class.mfct]](class.mfct "11.4.2Member functions") apply to static member
functions[.](#mfct-1.sentence-1)
— *end note*]
[2](#mfct-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2772)
[*Note [2](#mfct-note-2)*:
A static member function does not have a this pointer ([[expr.prim.this]](expr.prim.this "7.5.3This"))[.](#mfct-2.sentence-1)
A static member function cannot be qualified with const,volatile, or virtual ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#mfct-2.sentence-2)
— *end note*]
#### [11.4.9.3](#data) Static data members [[class.static.data]](class.static.data)
[1](#data-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2783)
A static data member is not part of the subobjects of a class[.](#data-1.sentence-1)
If a
static data member is declared thread_local there is one copy of
the member per thread[.](#data-1.sentence-2)
If a static data member is not declaredthread_local there is one copy of the data member that is shared by all
the objects of the class[.](#data-1.sentence-3)
[2](#data-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2790)
A static data member shall not be mutable ([[dcl.stc]](dcl.stc "9.2.2Storage class specifiers"))[.](#data-2.sentence-1)
A static data member shall not be a direct member ([[class.mem]](class.mem "11.4Class members"))
of an unnamed ([[class.pre]](class.pre "11.1Preamble")) or local ([[class.local]](class.local "11.6Local class declarations")) class or
of a (possibly indirectly) nested class ([[class.nest]](class.nest "11.4.12Nested class declarations")) thereof[.](#data-2.sentence-2)
[3](#data-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2796)
The declaration of a non-inline
static data member in its class definition
is not a definition and may be of an incomplete type other thancv void[.](#data-3.sentence-1)
[*Note [1](#data-note-1)*:
The [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") in the definition of a
static data member is in the scope of its
class ([[basic.scope.class]](basic.scope.class "6.4.7Class scope"))[.](#data-3.sentence-2)
— *end note*]
[*Example [1](#data-example-1)*: class process {static process* run_chain; static process* running;};
process* process::running = get_main();
process* process::run_chain = running;
The definition of the static data member run_chain of classprocess inhabits the global scope; the notationprocess::run_chain indicates that the member run_chain is a member of class process and in the scope of classprocess[.](#data-3.sentence-3)
In the static data member definition, the[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") expression refers to the static data
member running of class process[.](#data-3.sentence-4)
— *end example*]
[*Note [2](#data-note-2)*:
Once the static data member has been defined, it exists even if
no objects of its class have been created[.](#data-3.sentence-5)
[*Example [2](#data-example-2)*:
In the example above, run_chain and running exist even
if no objects of class process are created by the program[.](#data-3.sentence-6)
— *end example*]
The initialization and destruction of static data members is described in[[basic.start.static]](basic.start.static "6.10.3.2Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3Dynamic initialization of non-block variables"), and [[basic.start.term]](basic.start.term "6.10.3.4Termination")[.](#data-3.sentence-7)
— *end note*]
[4](#data-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2840)
If a non-volatile non-inline const static data member is
of integral or enumeration type,
its declaration in the class definition can specify a[*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") in which every[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") that is an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") is a constant expression ([[expr.const]](expr.const "7.7Constant expressions"))[.](#data-4.sentence-1)
The member shall still be defined in a namespace scope if
it is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) in the program and the
namespace scope definition shall not contain an [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")[.](#data-4.sentence-2)
The declaration of an inline static data member (which is a definition)
may specify a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")[.](#data-4.sentence-3)
If the
member is declared with the constexpr specifier, it may be
redeclared in namespace scope with no initializer (this usage is
deprecated; see [[depr.static.constexpr]](depr.static.constexpr "D.7Redeclaration of static constexpr data members"))[.](#data-4.sentence-4)
Declarations of other
static data members shall not specify a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")[.](#data-4.sentence-5)
[5](#data-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2857)
[*Note [3](#data-note-3)*:
There is exactly one definition of a static data member
that is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) in a valid program[.](#data-5.sentence-1)
— *end note*]
[6](#data-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2863)
[*Note [4](#data-note-4)*:
Static data members of a class in namespace scope have the linkage of the name of the class ([[basic.link]](basic.link "6.7Program and linkage"))[.](#data-6.sentence-1)
— *end note*]

View File

@@ -0,0 +1,120 @@
[class.static.data]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.static.data)
### 11.4.9 Static members [[class.static]](class.static#data)
#### 11.4.9.3 Static data members [class.static.data]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2783)
A static data member is not part of the subobjects of a class[.](#1.sentence-1)
If a
static data member is declared thread_local there is one copy of
the member per thread[.](#1.sentence-2)
If a static data member is not declaredthread_local there is one copy of the data member that is shared by all
the objects of the class[.](#1.sentence-3)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2790)
A static data member shall not be mutable ([[dcl.stc]](dcl.stc "9.2.2Storage class specifiers"))[.](#2.sentence-1)
A static data member shall not be a direct member ([[class.mem]](class.mem "11.4Class members"))
of an unnamed ([[class.pre]](class.pre "11.1Preamble")) or local ([[class.local]](class.local "11.6Local class declarations")) class or
of a (possibly indirectly) nested class ([[class.nest]](class.nest "11.4.12Nested class declarations")) thereof[.](#2.sentence-2)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2796)
The declaration of a non-inline
static data member in its class definition
is not a definition and may be of an incomplete type other thancv void[.](#3.sentence-1)
[*Note [1](#note-1)*:
The [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") in the definition of a
static data member is in the scope of its
class ([[basic.scope.class]](basic.scope.class "6.4.7Class scope"))[.](#3.sentence-2)
— *end note*]
[*Example [1](#example-1)*: class process {static process* run_chain; static process* running;};
process* process::running = get_main();
process* process::run_chain = running;
The definition of the static data member run_chain of classprocess inhabits the global scope; the notationprocess::run_chain indicates that the member run_chain is a member of class process and in the scope of classprocess[.](#3.sentence-3)
In the static data member definition, the[*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]") expression refers to the static data
member running of class process[.](#3.sentence-4)
— *end example*]
[*Note [2](#note-2)*:
Once the static data member has been defined, it exists even if
no objects of its class have been created[.](#3.sentence-5)
[*Example [2](#example-2)*:
In the example above, run_chain and running exist even
if no objects of class process are created by the program[.](#3.sentence-6)
— *end example*]
The initialization and destruction of static data members is described in[[basic.start.static]](basic.start.static "6.10.3.2Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3Dynamic initialization of non-block variables"), and [[basic.start.term]](basic.start.term "6.10.3.4Termination")[.](#3.sentence-7)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2840)
If a non-volatile non-inline const static data member is
of integral or enumeration type,
its declaration in the class definition can specify a[*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]") in which every[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1General[dcl.init.general]") that is an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19Assignment and compound assignment operators[expr.assign]") is a constant expression ([[expr.const]](expr.const "7.7Constant expressions"))[.](#4.sentence-1)
The member shall still be defined in a namespace scope if
it is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) in the program and the
namespace scope definition shall not contain an [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")[.](#4.sentence-2)
The declaration of an inline static data member (which is a definition)
may specify a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")[.](#4.sentence-3)
If the
member is declared with the constexpr specifier, it may be
redeclared in namespace scope with no initializer (this usage is
deprecated; see [[depr.static.constexpr]](depr.static.constexpr "D.7Redeclaration of static constexpr data members"))[.](#4.sentence-4)
Declarations of other
static data members shall not specify a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1General[dcl.init.general]")[.](#4.sentence-5)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2857)
[*Note [3](#note-3)*:
There is exactly one definition of a static data member
that is odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) in a valid program[.](#5.sentence-1)
— *end note*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2863)
[*Note [4](#note-4)*:
Static data members of a class in namespace scope have the linkage of the name of the class ([[basic.link]](basic.link "6.7Program and linkage"))[.](#6.sentence-1)
— *end note*]

View File

@@ -0,0 +1,44 @@
[class.static.general]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.static.general)
### 11.4.9 Static members [[class.static]](class.static#general)
#### 11.4.9.1 General [class.static.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2732)
A static member s of class X may be referred to
using the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") expression X::s; it is not
necessary to use the class member access syntax ([[expr.ref]](expr.ref "7.6.1.5Class member access")) to
refer to a static member[.](#1.sentence-1)
A static member may be
referred to using the class member access syntax, in which case the
object expression is evaluated[.](#1.sentence-2)
[*Example [1](#example-1)*: struct process {static void reschedule();};
process& g();
void f() { process::reschedule(); // OK, no object necessary g().reschedule(); // g() is called} — *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2753)
Static members obey the usual class member access rules ([[class.access]](class.access "11.8Member access control"))[.](#2.sentence-1)
When used in the declaration of a class
member, the static specifier shall only be used in the member
declarations that appear within the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of
the class definition[.](#2.sentence-2)
[*Note [1](#note-1)*:
It cannot be specified in member declarations that appear in namespace scope[.](#2.sentence-3)
— *end note*]

View File

@@ -0,0 +1,32 @@
[class.static.mfct]
# 11 Classes [[class]](./#class)
## 11.4 Class members [[class.mem]](class.mem#class.static.mfct)
### 11.4.9 Static members [[class.static]](class.static#mfct)
#### 11.4.9.2 Static member functions [class.static.mfct]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2766)
[*Note [1](#note-1)*:
The rules described in [[class.mfct]](class.mfct "11.4.2Member functions") apply to static member
functions[.](#1.sentence-1)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2772)
[*Note [2](#note-2)*:
A static member function does not have a this pointer ([[expr.prim.this]](expr.prim.this "7.5.3This"))[.](#2.sentence-1)
A static member function cannot be qualified with const,volatile, or virtual ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))[.](#2.sentence-2)
— *end note*]

423
cppdraft/class/temporary.md Normal file
View File

@@ -0,0 +1,423 @@
[class.temporary]
# 6 Basics [[basic]](./#basic)
## 6.8 Memory and objects [[basic.memobj]](basic.memobj#class.temporary)
### 6.8.7 Temporary objects [class.temporary]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4614)
A [*temporary object*](#def:object,temporary "6.8.7Temporary objects[class.temporary]") is an object created
- [(1.1)](#1.1)
when a prvalue is converted to an xvalue ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion")) and
- [(1.2)](#1.2)
when needed by the implementation to pass or return an object of suitable type (see below)[.](#1.sentence-1)
Even when the creation of the temporary object is
unevaluated ([[expr.context]](expr.context "7.2.3Context dependence")),
all the semantic restrictions shall be respected as if the temporary object
had been created and later destroyed[.](#1.sentence-2)
[*Note [1](#note-1)*:
This includes accessibility ([[class.access]](class.access "11.8Member access control")) and whether it is deleted,
for the constructor selected and for the destructor[.](#1.sentence-3)
However, in the special
case of the operand of a[*decltype-specifier*](dcl.type.decltype#nt:decltype-specifier "9.2.9.6Decltype specifiers[dcl.type.decltype]") ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6Decltype specifiers")), no temporary is introduced,
so the foregoing does not apply to such a prvalue[.](#1.sentence-4)
— *end note*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4638)
The materialization of a temporary object is generally
delayed as long as possible
in order to avoid creating unnecessary temporary objects[.](#2.sentence-1)
[*Note [2](#note-2)*:
Temporary objects are materialized:
- [(2.1)](#2.1)
when binding a reference to a prvalue ([[dcl.init.ref]](dcl.init.ref "9.5.4References"), [[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7Dynamic cast"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11Const cast"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)")),
- [(2.2)](#2.2)
when performing certain member accesses on a class prvalue ([[expr.ref]](expr.ref "7.6.1.5Class member access"), [[expr.mptr.oper]](expr.mptr.oper "7.6.4Pointer-to-member operators")),
- [(2.3)](#2.3)
when invoking an implicit object member function on a class prvalue ([[expr.call]](expr.call "7.6.1.3Function call")),
- [(2.4)](#2.4)
when performing an array-to-pointer conversion or subscripting on an array prvalue ([[conv.array]](conv.array "7.3.3Array-to-pointer conversion"), [[expr.sub]](expr.sub "7.6.1.2Subscripting")),
- [(2.5)](#2.5)
when initializing an object of type std::initializer_list<T> from a [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1General[dcl.init.general]") ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization")),
- [(2.6)](#2.6)
for certain unevaluated operands ([[expr.typeid]](expr.typeid "7.6.1.8Type identification"), [[expr.sizeof]](expr.sizeof "7.6.2.5Sizeof")), and
- [(2.7)](#2.7)
when a prvalue that has type other than cv void appears as a discarded-value expression ([[expr.context]](expr.context "7.2.3Context dependence"))[.](#2.sentence-2)
— *end note*]
[*Example [1](#example-1)*:
Consider the following code:class X {public: X(int);
X(const X&);
X& operator=(const X&); ~X();};
class Y {public: Y(int);
Y(Y&&); ~Y();};
X f(X);
Y g(Y);
void h() { X a(1);
X b = f(X(2));
Y c = g(Y(3));
a = f(a);}
X(2) is constructed in the space used to hold f()'s argument andY(3) is constructed in the space used to hold g()'s argument[.](#2.sentence-4)
Likewise,f()'s result is constructed directly in b andg()'s result is constructed directly in c[.](#2.sentence-5)
On the other hand, the expressiona = f(a) requires a temporary for
the result of f(a),
which is materialized so that the reference parameter
of X::operator=(const X&) can bind to it[.](#2.sentence-6)
— *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4706)
When an object of class type X is passed to or returned from a potentially-evaluated function call,
if X is
- [(3.1)](#3.1)
a scalar type or
- [(3.2)](#3.2)
a class type that
has at least one eligible copy or move constructor ([[special]](special "11.4.4Special member functions")),
where each such constructor is trivial,
and the destructor of X is either trivial or deleted,
implementations are permitted
to create temporary objects
to hold the function parameter or result object,
as follows:
- [(3.3)](#3.3)
The first such temporary object
is constructed from the function argument or return value, respectively[.](#3.3.sentence-1)
- [(3.4)](#3.4)
Each successive temporary object
is initialized from the previous one
as if by direct-initialization if X is a scalar type,
otherwise by using an eligible trivial constructor[.](#3.4.sentence-1)
- [(3.5)](#3.5)
The function parameter or return object is initialized
from the final temporary
as if by direct-initialization if X is a scalar type,
otherwise by using an eligible trivial constructor[.](#3.5.sentence-1)
(In all cases, the eligible constructor is used
even if that constructor is inaccessible
or would not be selected by overload resolution
to perform a copy or move of the object)[.](#3.sentence-2)
[*Note [3](#note-3)*:
This latitude is granted to allow objects
to be passed to or returned from functions in registers[.](#3.sentence-3)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4747)
Temporary objects are destroyed as the last step
in evaluating
the full-expression ([[intro.execution]](intro.execution "6.10.1Sequential execution"))
that (lexically) contains the point where
they were created[.](#4.sentence-1)
This is true even if that evaluation ends in throwing an exception[.](#4.sentence-2)
Thevalue computations andside effects of destroying a temporary object
are associated only with the full-expression, not with any specific
subexpression[.](#4.sentence-3)
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4765)
There are several contexts in which temporaries are destroyed at a different
point than the end of the full-expression[.](#5.sentence-1)
The first context is when a default constructor is called to initialize
an element of an array with no corresponding initializer ([[dcl.init]](dcl.init "9.5Initializers"))[.](#5.sentence-2)
The second context is when a copy constructor is called to copy an element of
an array while the entire array is copied ([[expr.prim.lambda.capture]](expr.prim.lambda.capture "7.5.6.3Captures"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors"))[.](#5.sentence-3)
In either case, if the constructor has one or more default arguments,
the destruction of every temporary created in a default argument is
sequenced before the construction of the next array element, if any[.](#5.sentence-4)
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4778)
The third context is when a reference binds to a temporary object[.](#6.sentence-1)[25](#footnote-25 "The same rules apply to initialization of an initializer_­list object ([dcl.init.list]) with its underlying temporary array.")
The temporary object to which the reference is bound or the temporary object
that is the complete object of a subobject to which the reference is bound
persists for the lifetime of the reference if the glvalue
to which the reference is bound
was obtained through one of the following:
- [(6.1)](#6.1)
a temporary materialization conversion ([[conv.rval]](conv.rval "7.3.5Temporary materialization conversion")),
- [(6.2)](#6.2)
( [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") ),
where [*expression*](expr.comma#nt:expression "7.6.20Comma operator[expr.comma]") is one of these expressions,
- [(6.3)](#6.3)
subscripting ([[expr.sub]](expr.sub "7.6.1.2Subscripting")) of an array operand,
where that operand is one of these expressions,
- [(6.4)](#6.4)
a class member access ([[expr.ref]](expr.ref "7.6.1.5Class member access")) using the . operator
where the left operand is one of these expressions and
the right operand designates a non-static data member of non-reference type,
- [(6.5)](#6.5)
a pointer-to-member operation ([[expr.mptr.oper]](expr.mptr.oper "7.6.4Pointer-to-member operators")) using the .* operator
where the left operand is one of these expressions and
the right operand is a pointer to data member of non-reference type,
- [(6.6)](#6.6)
a
* [(6.6.1)](#6.6.1)
const_cast ([[expr.const.cast]](expr.const.cast "7.6.1.11Const cast")),
* [(6.6.2)](#6.6.2)
static_cast ([[expr.static.cast]](expr.static.cast "7.6.1.9Static cast")),
* [(6.6.3)](#6.6.3)
dynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7Dynamic cast")), or
* [(6.6.4)](#6.6.4)
reinterpret_cast ([[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10Reinterpret cast"))
converting, without a user-defined conversion,
a glvalue operand that is one of these expressions
to a glvalue that refers
to the object designated by the operand, or
to its complete object or a subobject thereof,
- [(6.7)](#6.7)
a conditional expression ([[expr.cond]](expr.cond "7.6.16Conditional operator")) that is a glvalue
where the second or third operand is one of these expressions, or
- [(6.8)](#6.8)
a comma expression ([[expr.comma]](expr.comma "7.6.20Comma operator")) that is a glvalue
where the right operand is one of these expressions[.](#6.sentence-2)
[*Example [2](#example-2)*: template<typename T> using id = T;
int i = 1;int&& a = id<int[3]>{1, 2, 3}[i]; // temporary array has same lifetime as aconst int& b = static_cast<const int&>(0); // temporary int has same lifetime as bint&& c = cond ? id<int[3]>{1, 2, 3}[i] : static_cast<int&&>(0); // exactly one of the two temporaries is lifetime-extended — *end example*]
[*Note [4](#note-4)*:
An explicit type conversion ([[expr.type.conv]](expr.type.conv "7.6.1.4Explicit type conversion (functional notation)"), [[expr.cast]](expr.cast "7.6.3Explicit type conversion (cast notation)"))
is interpreted as
a sequence of elementary casts,
covered above[.](#6.sentence-3)
[*Example [3](#example-3)*: const int& x = (const int&)1; // temporary for value 1 has same lifetime as x — *end example*]
— *end note*]
[*Note [5](#note-5)*:
If a temporary object has a reference member initialized by another temporary object,
lifetime extension applies recursively to such a member's initializer[.](#6.sentence-4)
[*Example [4](#example-4)*: struct S {const int& m;};const S& s = S{1}; // both S and int temporaries have lifetime of s — *end example*]
— *end note*]
The exceptions to this lifetime rule are:
- [(6.9)](#6.9)
A temporary object bound to a reference parameter in a function call ([[expr.call]](expr.call "7.6.1.3Function call"))
persists until the completion of the full-expression containing the call[.](#6.9.sentence-1)
- [(6.10)](#6.10)
A temporary object bound to a reference element of
an aggregate of class type initialized from
a parenthesized [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]") ([[dcl.init]](dcl.init "9.5Initializers"))
persists until the completion of the full-expression
containing the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1General[expr.post.general]")[.](#6.10.sentence-1)
- [(6.11)](#6.11)
A temporary bound to a reference in a [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8New[expr.new]") ([[expr.new]](expr.new "7.6.2.8New")) persists until the completion of the full-expression containing the [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8New[expr.new]")[.](#6.11.sentence-1)
[*Note [6](#note-6)*:
This might introduce a dangling reference[.](#6.11.sentence-2)
— *end note*]
[*Example [5](#example-5)*: struct S { int mi; const std::pair<int,int>& mp; };
S a { 1, {2,3} };
S* p = new S{ 1, {2,3} }; // creates dangling reference — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4886)
The fourth context is when a temporary object
is created in the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") of
either a range-based for statement
or an enumerating expansion statement ([[stmt.expand]](stmt.expand "8.7Expansion statements"))[.](#7.sentence-1)
If such a temporary object would otherwise be destroyed
at the end of the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]") full-expression,
the object persists for the lifetime of the reference
initialized by the [*for-range-initializer*](stmt.pre#nt:for-range-initializer "8.1Preamble[stmt.pre]")[.](#7.sentence-2)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4896)
The fifth context is when a temporary object is created
in the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7Expansion statements[stmt.expand]") of an iterating or destructuring expansion statement[.](#8.sentence-1)
If such a temporary object would otherwise be destroyed
at the end of that [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7Expansion statements[stmt.expand]"),
the object persists for the lifetime of the reference
initialized by the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7Expansion statements[stmt.expand]"), if any[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4905)
The sixth context is when a temporary object
is created in a structured binding declaration ([[dcl.struct.bind]](dcl.struct.bind "9.7Structured binding declarations"))[.](#9.sentence-1)
Any temporary objects introduced by
the [*initializer*](dcl.init.general#nt:initializer "9.5.1General[dcl.init.general]")*s* for the variables
with unique names
are destroyed at the end of the structured binding declaration[.](#9.sentence-2)
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4913)
Let x and y each be either
a temporary object whose lifetime is not extended, or
a function parameter[.](#10.sentence-1)
If the lifetimes of x and y end at
the end of the same full-expression, andx is initialized before y, then
the destruction of y is sequenced before that of x[.](#10.sentence-2)
If the lifetime of two or more temporaries
with lifetimes extending beyond the full-expressions in which they were created
ends at the same point,
these temporaries are destroyed at that point in the reverse order of the
completion of their construction[.](#10.sentence-3)
In addition, the destruction of such temporaries shall
take into account the ordering of destruction of objects with static, thread, or
automatic storage duration ([[basic.stc.static]](basic.stc.static "6.8.6.2Static storage duration"), [[basic.stc.thread]](basic.stc.thread "6.8.6.3Thread storage duration"), [[basic.stc.auto]](basic.stc.auto "6.8.6.4Automatic storage duration"));
that is, ifobj1 is an object with the same storage duration as the temporary and
created before the temporary is created
the temporary shall be destroyed beforeobj1 is destroyed;
ifobj2 is an object with the same storage duration as the temporary and
created after the temporary is created
the temporary shall be destroyed afterobj2 is destroyed[.](#10.sentence-4)
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/basic.tex#L4944)
[*Example [6](#example-6)*: struct S { S();
S(int); friend S operator+(const S&, const S&); ~S();};
S obj1;const S& cr = S(16)+S(23);
S obj2;
The expressionS(16) + S(23) creates three temporaries:
a first temporaryT1 to hold the result of the expressionS(16),
a second temporaryT2 to hold the result of the expressionS(23),
and a third temporaryT3 to hold the result of the addition of these two expressions[.](#11.sentence-1)
The temporaryT3 is then bound to the referencecr[.](#11.sentence-2)
It is unspecified whetherT1 orT2 is created first[.](#11.sentence-3)
On an implementation whereT1 is created beforeT2,T2 shall be destroyed beforeT1[.](#11.sentence-4)
The temporariesT1 andT2 are bound to the reference parameters ofoperator+;
these temporaries are destroyed at the end of the full-expression
containing the call tooperator+[.](#11.sentence-5)
The temporaryT3 bound to the referencecr is destroyed at the end ofcr's
lifetime, that is, at the end of the program[.](#11.sentence-6)
In addition, the order in whichT3 is destroyed takes into account the destruction order of other objects with
static storage duration[.](#11.sentence-7)
That is, becauseobj1 is constructed beforeT3,
andT3 is constructed beforeobj2,obj2 shall be destroyed beforeT3,
andT3 shall be destroyed beforeobj1[.](#11.sentence-8)
— *end example*]
[25)](#footnote-25)[25)](#footnoteref-25)
The same rules apply to initialization of an initializer_list object ([[dcl.init.list]](dcl.init.list "9.5.5List-initialization")) with its
underlying temporary array[.](#footnote-25.sentence-1)

265
cppdraft/class/union.md Normal file
View File

@@ -0,0 +1,265 @@
[class.union]
# 11 Classes [[class]](./#class)
## 11.5 Unions [class.union]
### [11.5.1](#general) General [[class.union.general]](class.union.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3186)
A [*union*](#def:union "11.5.1General[class.union.general]") is a class defined with the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]")union[.](#general-1.sentence-1)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3190)
In a union,
a non-static data member is [*active*](#def:active,union_member "11.5.1General[class.union.general]") if its name refers to an object
whose lifetime has begun and has not ended ([[basic.life]](basic.life "6.8.4Lifetime"))[.](#general-2.sentence-1)
At most one of the non-static data members of an object of union type
can be active at any
time, that is, the value of at most one of the non-static data members can be
stored in a union at any time[.](#general-2.sentence-2)
[*Note [1](#general-note-1)*:
One special guarantee is made in order to
simplify the use of unions: If a standard-layout union contains several standard-layout
structs that share a common initial sequence ([[class.mem]](class.mem "11.4Class members")), and
if a non-static data member of an object of this standard-layout union type
is active and is one of the standard-layout structs,
the common initial sequence of any of the standard-layout struct members can be inspected;
see [[class.mem]](class.mem "11.4Class members")[.](#general-2.sentence-3)
— *end note*]
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3209)
The size of a union is sufficient to contain the largest
of its non-static data members[.](#general-3.sentence-1)
Each non-static data member is allocated
as if it were the sole member of a non-union class[.](#general-3.sentence-2)
[*Note [2](#general-note-2)*:
A union object and its non-static data members are
pointer-interconvertible ([[basic.compound]](basic.compound "6.9.4Compound types"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"))[.](#general-3.sentence-3)
As a consequence, all non-static data members of a
union object have the same address[.](#general-3.sentence-4)
— *end note*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3220)
A union can have member functions (including constructors and destructors),but it shall not have virtual ([[class.virtual]](class.virtual "11.7.3Virtual functions")) functions[.](#general-4.sentence-1)
A union shall not have
base classes[.](#general-4.sentence-2)
A union shall not be used as a base class[.](#general-4.sentence-3)
If a union contains a non-static data member of
reference type, the program is ill-formed[.](#general-4.sentence-4)
[*Note [3](#general-note-3)*:
If any non-static data member of a union has a non-trivial
copy constructor,
move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")),
copy assignment operator, or
move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator")),
the corresponding member function
of the union must be user-provided or it will
be implicitly deleted ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3Deleted definitions")) for the union[.](#general-4.sentence-5)
[*Example [1](#general-example-1)*:
Consider the following union:union U {int i; float f;
std::string s;};
Since std::string ([[string.classes]](string.classes "27.4String classes")) declares non-trivial versions of all of the special
member functions, U will have an implicitly deleted
copy/move constructor and copy/move assignment operator[.](#general-4.sentence-7)
The default constructor and destructor of U are both trivial
even though std::string has
a non-trivial default constructor and a non-trivial destructor[.](#general-4.sentence-8)
— *end example*]
— *end note*]
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3258)
When the left operand of an assignment operator
involves a member access expression ([[expr.ref]](expr.ref "7.6.1.5Class member access"))
that nominates a union member,
it may begin the lifetime of that union member,
as described below[.](#general-5.sentence-1)
For an expression E,
define the set S(E) of subexpressions of E as follows:
- [(5.1)](#general-5.1)
If E is of the form A.B,S(E) contains the elements of S(A),
and also contains A.B if B names a union member of a non-class, non-array type,
or of a class type with a trivial default constructor that is not deleted,
or an array of such types[.](#general-5.1.sentence-1)
- [(5.2)](#general-5.2)
If E is of the form A[B] and is interpreted as a built-in array subscripting operator,S(E) is S(A) if A is of array type,S(B) if B is of array type,
and empty otherwise[.](#general-5.2.sentence-1)
- [(5.3)](#general-5.3)
Otherwise, S(E) is empty[.](#general-5.3.sentence-1)
In an assignment expression of the form E1 = E2 that uses either the built-in assignment operator ([[expr.assign]](expr.assign "7.6.19Assignment and compound assignment operators"))
or a trivial assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator")),
for each element X of S(E1) and
each anonymous union member X ([[class.union.anon]](#anon "11.5.2Anonymous unions")) that
is a member of a union and
has such an element as an immediate subobject (recursively),
if modification of X would have undefined behavior under [[basic.life]](basic.life "6.8.4Lifetime"),
an object of the type of X is implicitly created
in the nominated storage;
no initialization is performed and
the beginning of its lifetime is sequenced after
the value computation of the left and right operands
and before the assignment[.](#general-5.sentence-3)
[*Note [4](#general-note-4)*:
This ends the lifetime of the previously-active
member of the union, if any ([[basic.life]](basic.life "6.8.4Lifetime"))[.](#general-5.sentence-4)
— *end note*]
[*Example [2](#general-example-2)*: union A { int x; int y[4]; };struct B { A a; };union C { B b; int k; };int f() { C c; // does not start lifetime of any union member c.b.a.y[3] = 4; // OK, S(c.b.a.y[3]) contains c.b and c.b.a.y;// creates objects to hold union members c.b and c.b.a.yreturn c.b.a.y[3]; // OK, c.b.a.y refers to newly created object (see [[basic.life]](basic.life "6.8.4Lifetime"))}struct X { const int a; int b; };union Y { X x; int k; };void g() { Y y = { { 1, 2 } }; // OK, y.x is active union member ([[class.mem]](class.mem "11.4Class members"))int n = y.x.a;
y.k = 4; // OK, ends lifetime of y.x, y.k is active member of union y.x.b = n; // undefined behavior: y.x.b modified outside its lifetime,// S(y.x.b) is empty because X's default constructor is deleted,// so union member y.x's lifetime does not implicitly start} — *end example*]
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3328)
[*Note [5](#general-note-5)*:
In cases where the above rule does not apply,
the active member of a union can only be changed by
the use of a placement [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]")[.](#general-6.sentence-1)
— *end note*]
[*Example [3](#general-example-3)*:
Consider an object u of a union type U having non-static data membersm of type M and n of type N[.](#general-6.sentence-2)
If M has a non-trivial
destructor and N has a non-trivial constructor (for instance, if they declare or inherit
virtual functions), the active member of u can be safely switched from m ton using the destructor and placement [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") as follows:u.m.~M();new (&u.n) N;
— *end example*]
### [11.5.2](#anon) Anonymous unions [[class.union.anon]](class.union.anon)
[1](#anon-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3349)
A union of the form
union { [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") } ;
is called an [*anonymous union*](#def:anonymous_union "11.5.2Anonymous unions[class.union.anon]"); it defines an unnamed type and
an unnamed object of that type called
an [*anonymous union member*](#def:member,anonymous_union "11.5.2Anonymous unions[class.union.anon]") if it is a non-static data member or
an [*anonymous union variable*](#def:variable,anonymous_union "11.5.2Anonymous unions[class.union.anon]") otherwise[.](#anon-1.sentence-1)
Each [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") in the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of an anonymous union shall either define one or more public non-static data members or
be a [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1Preamble[dcl.pre]")[.](#anon-1.sentence-2)
Nested types, anonymous unions, and functions
shall not be declared within an anonymous union[.](#anon-1.sentence-3)
The names of the members of an anonymous union
are bound in the scope inhabited by the union declaration[.](#anon-1.sentence-4)
[*Example [1](#anon-example-1)*: void f() {union { int a; const char* p; };
a = 1;
p = "Jennifer";}
Here a and p are used like ordinary (non-member)
variables, but since they are union members they have the same address[.](#anon-1.sentence-5)
— *end example*]
[2](#anon-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3383)
An anonymous union declared in the scope of a namespace with external linkage
shall use the [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") static[.](#anon-2.sentence-1)
Anonymous unions declared at block scope shall not use a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") that is not permitted in the declaration of a block variable[.](#anon-2.sentence-2)
An anonymous union declaration at class scope shall not have
a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]")[.](#anon-2.sentence-3)
[3](#anon-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3393)
[*Note [1](#anon-note-1)*:
A union for which objects, pointers, or references are declared is not an anonymous union[.](#anon-3.sentence-1)
[*Example [2](#anon-example-2)*: void f() {union { int aa; char* p; } obj, *ptr = &obj;
aa = 1; // error ptr->aa = 1; // OK}
The assignment to plain aa is ill-formed since the member name
is not visible outside the union, and even if it were visible, it is not
associated with any particular object[.](#anon-3.sentence-2)
— *end example*]
— *end note*]
[*Note [2](#anon-note-2)*:
Initialization of unions with no user-declared constructors is described
in [[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates")[.](#anon-3.sentence-3)
— *end note*]
[4](#anon-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3415)
A [*union-like class*](#def:class,union-like "11.5.2Anonymous unions[class.union.anon]") is a union or a class that has an anonymous union as a direct
member[.](#anon-4.sentence-1)
A union-like class X has a set of [*variant members*](#def:variant_member "11.5.2Anonymous unions[class.union.anon]")[.](#anon-4.sentence-2)
If X is a union, a non-static data member of X that is not an anonymous
union is a variant member of X[.](#anon-4.sentence-3)
In addition, a non-static data member of an
anonymous union that is a member of X is also a variant member of X[.](#anon-4.sentence-4)
At most one variant member of a union may have a default member initializer[.](#anon-4.sentence-5)
[*Example [3](#anon-example-3)*: union U {int x = 0; union {int k; }; union {int z; int y = 1; // error: initialization for second variant member of U};}; — *end example*]

View File

@@ -0,0 +1,95 @@
[class.union.anon]
# 11 Classes [[class]](./#class)
## 11.5 Unions [[class.union]](class.union#anon)
### 11.5.2 Anonymous unions [class.union.anon]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3349)
A union of the form
union { [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") } ;
is called an [*anonymous union*](#def:anonymous_union "11.5.2Anonymous unions[class.union.anon]"); it defines an unnamed type and
an unnamed object of that type called
an [*anonymous union member*](#def:member,anonymous_union "11.5.2Anonymous unions[class.union.anon]") if it is a non-static data member or
an [*anonymous union variable*](#def:variable,anonymous_union "11.5.2Anonymous unions[class.union.anon]") otherwise[.](#1.sentence-1)
Each [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") in the [*member-specification*](class.mem.general#nt:member-specification "11.4.1General[class.mem.general]") of an anonymous union shall either define one or more public non-static data members or
be a [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1Preamble[dcl.pre]")[.](#1.sentence-2)
Nested types, anonymous unions, and functions
shall not be declared within an anonymous union[.](#1.sentence-3)
The names of the members of an anonymous union
are bound in the scope inhabited by the union declaration[.](#1.sentence-4)
[*Example [1](#example-1)*: void f() {union { int a; const char* p; };
a = 1;
p = "Jennifer";}
Here a and p are used like ordinary (non-member)
variables, but since they are union members they have the same address[.](#1.sentence-5)
— *end example*]
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3383)
An anonymous union declared in the scope of a namespace with external linkage
shall use the [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") static[.](#2.sentence-1)
Anonymous unions declared at block scope shall not use a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]") that is not permitted in the declaration of a block variable[.](#2.sentence-2)
An anonymous union declaration at class scope shall not have
a [*storage-class-specifier*](dcl.stc#nt:storage-class-specifier "9.2.2Storage class specifiers[dcl.stc]")[.](#2.sentence-3)
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3393)
[*Note [1](#note-1)*:
A union for which objects, pointers, or references are declared is not an anonymous union[.](#3.sentence-1)
[*Example [2](#example-2)*: void f() {union { int aa; char* p; } obj, *ptr = &obj;
aa = 1; // error ptr->aa = 1; // OK}
The assignment to plain aa is ill-formed since the member name
is not visible outside the union, and even if it were visible, it is not
associated with any particular object[.](#3.sentence-2)
— *end example*]
— *end note*]
[*Note [2](#note-2)*:
Initialization of unions with no user-declared constructors is described
in [[dcl.init.aggr]](dcl.init.aggr "9.5.2Aggregates")[.](#3.sentence-3)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3415)
A [*union-like class*](#def:class,union-like "11.5.2Anonymous unions[class.union.anon]") is a union or a class that has an anonymous union as a direct
member[.](#4.sentence-1)
A union-like class X has a set of [*variant members*](#def:variant_member "11.5.2Anonymous unions[class.union.anon]")[.](#4.sentence-2)
If X is a union, a non-static data member of X that is not an anonymous
union is a variant member of X[.](#4.sentence-3)
In addition, a non-static data member of an
anonymous union that is a member of X is also a variant member of X[.](#4.sentence-4)
At most one variant member of a union may have a default member initializer[.](#4.sentence-5)
[*Example [3](#example-3)*: union U {int x = 0; union {int k; }; union {int z; int y = 1; // error: initialization for second variant member of U};}; — *end example*]

View File

@@ -0,0 +1,175 @@
[class.union.general]
# 11 Classes [[class]](./#class)
## 11.5 Unions [[class.union]](class.union#general)
### 11.5.1 General [class.union.general]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3186)
A [*union*](#def:union "11.5.1General[class.union.general]") is a class defined with the [*class-key*](class.pre#nt:class-key "11.1Preamble[class.pre]")union[.](#1.sentence-1)
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3190)
In a union,
a non-static data member is [*active*](#def:active,union_member "11.5.1General[class.union.general]") if its name refers to an object
whose lifetime has begun and has not ended ([[basic.life]](basic.life "6.8.4Lifetime"))[.](#2.sentence-1)
At most one of the non-static data members of an object of union type
can be active at any
time, that is, the value of at most one of the non-static data members can be
stored in a union at any time[.](#2.sentence-2)
[*Note [1](#note-1)*:
One special guarantee is made in order to
simplify the use of unions: If a standard-layout union contains several standard-layout
structs that share a common initial sequence ([[class.mem]](class.mem "11.4Class members")), and
if a non-static data member of an object of this standard-layout union type
is active and is one of the standard-layout structs,
the common initial sequence of any of the standard-layout struct members can be inspected;
see [[class.mem]](class.mem "11.4Class members")[.](#2.sentence-3)
— *end note*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3209)
The size of a union is sufficient to contain the largest
of its non-static data members[.](#3.sentence-1)
Each non-static data member is allocated
as if it were the sole member of a non-union class[.](#3.sentence-2)
[*Note [2](#note-2)*:
A union object and its non-static data members are
pointer-interconvertible ([[basic.compound]](basic.compound "6.9.4Compound types"), [[expr.static.cast]](expr.static.cast "7.6.1.9Static cast"))[.](#3.sentence-3)
As a consequence, all non-static data members of a
union object have the same address[.](#3.sentence-4)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3220)
A union can have member functions (including constructors and destructors),but it shall not have virtual ([[class.virtual]](class.virtual "11.7.3Virtual functions")) functions[.](#4.sentence-1)
A union shall not have
base classes[.](#4.sentence-2)
A union shall not be used as a base class[.](#4.sentence-3)
If a union contains a non-static data member of
reference type, the program is ill-formed[.](#4.sentence-4)
[*Note [3](#note-3)*:
If any non-static data member of a union has a non-trivial
copy constructor,
move constructor ([[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors")),
copy assignment operator, or
move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator")),
the corresponding member function
of the union must be user-provided or it will
be implicitly deleted ([[dcl.fct.def.delete]](dcl.fct.def.delete "9.6.3Deleted definitions")) for the union[.](#4.sentence-5)
[*Example [1](#example-1)*:
Consider the following union:union U {int i; float f;
std::string s;};
Since std::string ([[string.classes]](string.classes "27.4String classes")) declares non-trivial versions of all of the special
member functions, U will have an implicitly deleted
copy/move constructor and copy/move assignment operator[.](#4.sentence-7)
The default constructor and destructor of U are both trivial
even though std::string has
a non-trivial default constructor and a non-trivial destructor[.](#4.sentence-8)
— *end example*]
— *end note*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3258)
When the left operand of an assignment operator
involves a member access expression ([[expr.ref]](expr.ref "7.6.1.5Class member access"))
that nominates a union member,
it may begin the lifetime of that union member,
as described below[.](#5.sentence-1)
For an expression E,
define the set S(E) of subexpressions of E as follows:
- [(5.1)](#5.1)
If E is of the form A.B,S(E) contains the elements of S(A),
and also contains A.B if B names a union member of a non-class, non-array type,
or of a class type with a trivial default constructor that is not deleted,
or an array of such types[.](#5.1.sentence-1)
- [(5.2)](#5.2)
If E is of the form A[B] and is interpreted as a built-in array subscripting operator,S(E) is S(A) if A is of array type,S(B) if B is of array type,
and empty otherwise[.](#5.2.sentence-1)
- [(5.3)](#5.3)
Otherwise, S(E) is empty[.](#5.3.sentence-1)
In an assignment expression of the form E1 = E2 that uses either the built-in assignment operator ([[expr.assign]](expr.assign "7.6.19Assignment and compound assignment operators"))
or a trivial assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator")),
for each element X of S(E1) and
each anonymous union member X ([[class.union.anon]](class.union.anon "11.5.2Anonymous unions")) that
is a member of a union and
has such an element as an immediate subobject (recursively),
if modification of X would have undefined behavior under [[basic.life]](basic.life "6.8.4Lifetime"),
an object of the type of X is implicitly created
in the nominated storage;
no initialization is performed and
the beginning of its lifetime is sequenced after
the value computation of the left and right operands
and before the assignment[.](#5.sentence-3)
[*Note [4](#note-4)*:
This ends the lifetime of the previously-active
member of the union, if any ([[basic.life]](basic.life "6.8.4Lifetime"))[.](#5.sentence-4)
— *end note*]
[*Example [2](#example-2)*: union A { int x; int y[4]; };struct B { A a; };union C { B b; int k; };int f() { C c; // does not start lifetime of any union member c.b.a.y[3] = 4; // OK, S(c.b.a.y[3]) contains c.b and c.b.a.y;// creates objects to hold union members c.b and c.b.a.yreturn c.b.a.y[3]; // OK, c.b.a.y refers to newly created object (see [[basic.life]](basic.life "6.8.4Lifetime"))}struct X { const int a; int b; };union Y { X x; int k; };void g() { Y y = { { 1, 2 } }; // OK, y.x is active union member ([[class.mem]](class.mem "11.4Class members"))int n = y.x.a;
y.k = 4; // OK, ends lifetime of y.x, y.k is active member of union y.x.b = n; // undefined behavior: y.x.b modified outside its lifetime,// S(y.x.b) is empty because X's default constructor is deleted,// so union member y.x's lifetime does not implicitly start} — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3328)
[*Note [5](#note-5)*:
In cases where the above rule does not apply,
the active member of a union can only be changed by
the use of a placement [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]")[.](#6.sentence-1)
— *end note*]
[*Example [3](#example-3)*:
Consider an object u of a union type U having non-static data membersm of type M and n of type N[.](#6.sentence-2)
If M has a non-trivial
destructor and N has a non-trivial constructor (for instance, if they declare or inherit
virtual functions), the active member of u can be safely switched from m ton using the destructor and placement [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]") as follows:u.m.~M();new (&u.n) N;
— *end example*]

332
cppdraft/class/virtual.md Normal file
View File

@@ -0,0 +1,332 @@
[class.virtual]
# 11 Classes [[class]](./#class)
## 11.7 Derived classes [[class.derived]](class.derived#class.virtual)
### 11.7.3 Virtual functions [class.virtual]
[1](#1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3830)
A non-static member function is a [*virtual function*](#def:function,virtual "11.7.3Virtual functions[class.virtual]") if it is first declared with the keyword virtual or
if it overrides a virtual member function declared in a base class
(see below)[.](#1.sentence-1)[92](#footnote-92 "The use of the virtual specifier in the declaration of an overriding function is valid but redundant (has empty semantics).")
[*Note [1](#note-1)*:
Virtual functions support dynamic binding and object-oriented
programming[.](#1.sentence-2)
— *end note*]
A class with a virtual member function is called a [*polymorphic class*](#def:class,polymorphic "11.7.3Virtual functions[class.virtual]")[.](#1.sentence-3)[93](#footnote-93 "If all virtual functions are immediate functions, the class is still polymorphic even if its internal representation does not otherwise require any additions for that polymorphic behavior.")
[2](#2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3853)
If a virtual member function F is declared in a class B, and,
in a class D derived (directly or indirectly) from B,
a declaration of a member function G corresponds ([[basic.scope.scope]](basic.scope.scope "6.4.1General")) to a declaration of F,
ignoring trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")*s*,
then G [*overrides*](#def:function,virtual,override "11.7.3Virtual functions[class.virtual]")[94](#footnote-94 "A function with the same name but a different parameter list ([over]) as a virtual function is not necessarily virtual and does not override. Access control ([class.access]) is not considered in determining overriding.")F[.](#2.sentence-1)
For convenience, we say that any virtual function overrides itself[.](#2.sentence-2)
A virtual member function V of a class object S is a [*final
overrider*](#def:final_overrider "11.7.3Virtual functions[class.virtual]") unless the most derived class ([[intro.object]](intro.object "6.8.2Object model")) of which S is a
base class subobject (if any) has another member function that overrides V[.](#2.sentence-3)
In a derived class, if a virtual member function of a base class subobject
has more than one final overrider, the program is ill-formed[.](#2.sentence-4)
[*Example [1](#example-1)*: struct A {virtual void f();};struct B : virtual A {virtual void f();};struct C : B , virtual A {using A::f;};
void foo() { C c;
c.f(); // calls B::f, the final overrider c.C::f(); // calls A::f because of the using-declaration} — *end example*]
[*Example [2](#example-2)*: struct A { virtual void f(); };struct B : A { };struct C : A { void f(); };struct D : B, C { }; // OK, A::f and C::f are the final overriders// for the B and C subobjects, respectively — *end example*]
[3](#3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3906)
[*Note [2](#note-2)*:
A virtual member function does not have to be visible to be overridden,
for example,struct B {virtual void f();};struct D : B {void f(int);};struct D2 : D {void f();}; the function f(int) in class D hides the virtual
function f() in its base class B; D::f(int) is
not a virtual function[.](#3.sentence-1)
However, f() declared in classD2 has the same name and the same parameter list asB::f(), and therefore is a virtual function that overrides the
function B::f() even though B::f() is not visible in
class D2[.](#3.sentence-2)
— *end note*]
[4](#4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3930)
If a virtual function f in some class B is marked with the[*virt-specifier*](class.mem.general#nt:virt-specifier "11.4.1General[class.mem.general]") final and in a class D derived from B a function D::f overrides B::f, the program is ill-formed[.](#4.sentence-1)
[*Example [3](#example-3)*: struct B {virtual void f() const final;};
struct D : B {void f() const; // error: D::f attempts to override final B::f}; — *end example*]
[5](#5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3946)
If a virtual function is marked with the [*virt-specifier*](class.mem.general#nt:virt-specifier "11.4.1General[class.mem.general]") override and
does not override a member function of a base class, the program is ill-formed[.](#5.sentence-1)
[*Example [4](#example-4)*: struct B {virtual void f(int);};
struct D : B {virtual void f(long) override; // error: wrong signature overriding B::fvirtual void f(int) override; // OK}; — *end example*]
[6](#6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3962)
A virtual function shall not have a trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") ([[dcl.decl]](dcl.decl "9.3Declarators"))[.](#6.sentence-1)
[*Example [5](#example-5)*: template<typename T>struct A {virtual void f() requires true; // error: virtual function cannot be constrained ([[temp.constr.decl]](temp.constr.decl "13.5.3Constrained declarations"))}; — *end example*]
[7](#7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3973)
The [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]"), or lack thereof, of an overriding function
shall be the same as that of the overridden function[.](#7.sentence-1)
[8](#8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3977)
The return type of an overriding function shall be either identical to
the return type of the overridden function or [*covariant*](#def:return_type,covariant "11.7.3Virtual functions[class.virtual]") with
the classes of the functions[.](#8.sentence-1)
If a function D::f overrides a
function B::f, the return types of the functions are covariant
if they satisfy the following criteria:
- [(8.1)](#8.1)
both are pointers to classes, both are lvalue references to
classes, or both are rvalue references to classes[95](#footnote-95 "Multi-level pointers to classes or references to multi-level pointers to classes are not allowed.")
- [(8.2)](#8.2)
the class in the return type of B::f is the same class as
the class in the return type of D::f, or is an unambiguous and
accessible direct or indirect base class of the class in the return type
of D::f
- [(8.3)](#8.3)
both pointers or references have the same cv-qualification and the
class type in the return type of D::f has the same
cv-qualification as or less cv-qualification than the class type in the
return type of B::f[.](#8.sentence-2)
[9](#9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4002)
If the class type in the covariant return type of D::f differs from that ofB::f, the class type in the return type of D::f shall be
complete at the locus ([[basic.scope.pdecl]](basic.scope.pdecl "6.4.2Point of declaration")) of the overriding declaration or shall be the
class type D[.](#9.sentence-1)
When the overriding function is called as the
final overrider of the overridden function, its result is converted to
the type returned by the (statically chosen) overridden
function ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#9.sentence-2)
[*Example [6](#example-6)*: class B { };class D : private B { friend class Derived; };struct Base {virtual void vf1(); virtual void vf2(); virtual void vf3(); virtual B* vf4(); virtual B* vf5(); void f();};
struct No_good : public Base { D* vf4(); // error: B (base class of D) inaccessible};
class A;struct Derived : public Base {void vf1(); // virtual and overrides Base::vf1()void vf2(int); // not virtual, hides Base::vf2()char vf3(); // error: invalid difference in return type only D* vf4(); // OK, returns pointer to derived class A* vf5(); // error: returns pointer to incomplete classvoid f();};
void g() { Derived d;
Base* bp = &d; // standard conversion:// Derived* to Base* bp->vf1(); // calls Derived::vf1() bp->vf2(); // calls Base::vf2() bp->f(); // calls Base::f() (not virtual) B* p = bp->vf4(); // calls Derived::vf4() and converts the// result to B* Derived* dp = &d;
D* q = dp->vf4(); // calls Derived::vf4() and does not// convert the result to B* dp->vf2(); // error: argument mismatch} — *end example*]
[10](#10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4054)
[*Note [3](#note-3)*:
The interpretation of the call of a virtual function depends on the type
of the object for which it is called (the dynamic type), whereas the
interpretation of a call of a non-virtual member function depends only
on the type of the pointer or reference denoting that object (the static
type) ([[expr.call]](expr.call "7.6.1.3Function call"))[.](#10.sentence-1)
— *end note*]
[11](#11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4063)
[*Note [4](#note-4)*:
The virtual specifier implies membership, so a virtual function
cannot be a non-member ([[dcl.fct.spec]](dcl.fct.spec "9.2.3Function specifiers")) function[.](#11.sentence-1)
Nor can a virtual
function be a static member, since a virtual function call relies on a
specific object for determining which function to invoke[.](#11.sentence-2)
A virtual
function declared in one class can be declared a friend ([[class.friend]](class.friend "11.8.4Friends")) in
another class[.](#11.sentence-3)
— *end note*]
[12](#12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4073)
A virtual function declared in a class shall be defined, or declared
pure ([[class.abstract]](class.abstract "11.7.4Abstract classes")) in that class, or both; no diagnostic is
required ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))[.](#12.sentence-1)
[13](#13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4080)
[*Example [7](#example-7)*:
Here are some uses of virtual functions with multiple base classes:struct A {virtual void f();};
struct B1 : A { // note non-virtual derivationvoid f();};
struct B2 : A {void f();};
struct D : B1, B2 { // D has two separate A subobjects};
void foo() { D d;// A* ap = &d; // would be ill-formed: ambiguous B1* b1p = &d;
A* ap = b1p;
D* dp = &d;
ap->f(); // calls D::B1::f dp->f(); // error: ambiguous}
In class D above there are two occurrences of class A and hence two occurrences of the virtual member function A::f[.](#13.sentence-2)
The final overrider of B1::A::f is B1::f and the final
overrider of B2::A::f is B2::f[.](#13.sentence-3)
— *end example*]
[14](#14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4116)
[*Example [8](#example-8)*:
The following example shows a function that does not have a unique final
overrider:struct A {virtual void f();};
struct VB1 : virtual A { // note virtual derivationvoid f();};
struct VB2 : virtual A {void f();};
struct Error : VB1, VB2 { // error};
struct Okay : VB1, VB2 {void f();};
Both VB1::f and VB2::f override A::f but there
is no overrider of both of them in class Error[.](#14.sentence-2)
This example is
therefore ill-formed[.](#14.sentence-3)
Class Okay is well-formed, however,
because Okay::f is a final overrider[.](#14.sentence-4)
— *end example*]
[15](#15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4146)
[*Example [9](#example-9)*:
The following example uses the well-formed classes from above[.](#15.sentence-1)
struct VB1a : virtual A { // does not declare f};
struct Da : VB1a, VB2 {};
void foe() { VB1a* vb1ap = new Da;
vb1ap->f(); // calls VB2::f} — *end example*]
[16](#16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4163)
Explicit qualification with the scope operator ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3Qualified names"))
suppresses the virtual call mechanism[.](#16.sentence-1)
[*Example [10](#example-10)*: class B { public: virtual void f(); };class D : public B { public: void f(); };
void D::f() { /* ... */ B::f(); }
Here, the function call inD::f really does callB::f and notD::f[.](#16.sentence-2)
— *end example*]
[17](#17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4184)
A deleted function ([[dcl.fct.def]](dcl.fct.def "9.6Function definitions")) shall
not override a function that is not deleted[.](#17.sentence-1)
Likewise,
a function that is not deleted shall not override a
deleted function[.](#17.sentence-2)
[18](#18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L4191)
A consteval virtual function shall not override
a virtual function that is not consteval[.](#18.sentence-1)
A consteval virtual function shall not be overridden by
a virtual function that is not consteval[.](#18.sentence-2)
[92)](#footnote-92)[92)](#footnoteref-92)
The use of the virtual specifier in the
declaration of an overriding function is valid but redundant (has empty
semantics)[.](#footnote-92.sentence-1)
[93)](#footnote-93)[93)](#footnoteref-93)
If
all virtual functions are immediate functions,
the class is still polymorphic even if
its internal representation does not otherwise require
any additions for that polymorphic behavior[.](#footnote-93.sentence-1)
[94)](#footnote-94)[94)](#footnoteref-94)
A function
with the same name but a different parameter list ([[over]](over "12Overloading"))
as a virtual function is not necessarily virtual and
does not override[.](#footnote-94.sentence-1)
Access control ([[class.access]](class.access "11.8Member access control")) is not considered in
determining overriding[.](#footnote-94.sentence-2)
[95)](#footnote-95)[95)](#footnoteref-95)
Multi-level pointers to classes or references to multi-level pointers to
classes are not allowed[.](#footnote-95.sentence-1)