Init
This commit is contained in:
117
cppdraft/class/abstract.md
Normal file
117
cppdraft/class/abstract.md
Normal 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.4 Abstract classes [class.abstract]") by using a[*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1 General [class.mem.general]") ([[class.mem]](class.mem "11.4 Class 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.4 Abstract 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.2 Declarations and definitions"), [[class.mem]](class.mem "11.4 Class 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.7 Destructors")), the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") syntax ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified 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.1 General [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.6 Functions")) or called ([[expr.call]](expr.call "7.6.1.3 Function call")),
|
||||
except as specified in [[dcl.type.simple]](dcl.type.simple "9.2.9.3 Simple 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.9 Static cast"), [[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10 Reinterpret cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11 Const cast")),
|
||||
because the resulting prvalue would be of abstract class type ([[basic.lval]](basic.lval "7.2.1 Value 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.3 Virtual 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
673
cppdraft/class/access.md
Normal 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.5 Protected 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.3 One-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.4 Friends")) and[*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*s* ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"))[.](#general-4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
When a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The 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.1 General [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.1 General [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.1 General [class.derived.general]")*s* must be deferred until the entire [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1 General [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.7 Default 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.2 Implicit 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.3 Names of template specializations [temp.names]") ([[temp.param]](temp.param "13.2 Template 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.1 General [class.derived.general]") ([[class.derived]](class.derived "11.7 Derived classes")):
|
||||
|
||||
[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1 General [class.derived.general]") : [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]")opt
|
||||
|
||||
An[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1 General [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.1 General [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.7 Derived 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.1 General [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.1 Preamble [class.pre]")struct andprivate is assumed when the class is
|
||||
defined with the [*class-key*](class.pre#nt:class-key "11.1 Preamble [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.12 Pointer conversions")) and
|
||||
explicit casts ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit 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.3 Accessibility 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.12 Pointer conversions"), [[conv.mem]](conv.mem "7.3.13 Pointer-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.3 Accessibility 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.9 Expression 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.3 Qualified names [expr.prim.id.qual]") is used, or implicit, e.g., when a class member access operator ([[expr.ref]](expr.ref "7.6.1.5 Class 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.3 Qualified 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.3 Qualified names [expr.prim.id.qual]") of the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified 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.9 Expression 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.1 General [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.1 General [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.1 Preamble [dcl.pre]") in
|
||||
a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble"), [[temp.friend]](temp.friend "13.7.5 Friends"))[.](#class.friend-3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
If a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1 General [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.1 General [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.6 Local 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.8 The 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.2 Storage class specifiers [dcl.stc]") shall appear in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [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.4 Class members"))
|
||||
portion of the class[*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [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.4 Meaning of declarators"), [[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated 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.3 Accessibility 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.2 Unary operators")), the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified 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.5 Class 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*]
|
||||
191
cppdraft/class/access/base.md
Normal file
191
cppdraft/class/access/base.md
Normal 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.7 Derived 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.1 General [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.1 Preamble [class.pre]")struct andprivate is assumed when the class is
|
||||
defined with the [*class-key*](class.pre#nt:class-key "11.1 Preamble [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.12 Pointer conversions")) and
|
||||
explicit casts ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit 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.3 Accessibility 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.12 Pointer conversions"), [[conv.mem]](conv.mem "7.3.13 Pointer-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.3 Accessibility 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.9 Expression 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.3 Qualified names [expr.prim.id.qual]") is used, or implicit, e.g., when a class member access operator ([[expr.ref]](expr.ref "7.6.1.5 Class 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.3 Qualified 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.3 Qualified names [expr.prim.id.qual]") of the[*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified 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.9 Expression 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.8 Member 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)
|
||||
181
cppdraft/class/access/general.md
Normal file
181
cppdraft/class/access/general.md
Normal 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.5 Protected 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.3 One-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.4 Friends")) and[*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")*s* ([[namespace.udecl]](namespace.udecl "9.10 The using declaration"))[.](#4.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
When a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The 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.8 Member 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.1 General [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.1 General [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.1 General [class.derived.general]")*s* must be deferred until the entire [*base-specifier-list*](class.derived.general#nt:base-specifier-list "11.7.1 General [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.7 Default 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.2 Implicit 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.3 Names of template specializations [temp.names]") ([[temp.param]](temp.param "13.2 Template 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)
|
||||
18
cppdraft/class/access/nest.md
Normal file
18
cppdraft/class/access/nest.md
Normal 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.8 Member 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*]
|
||||
55
cppdraft/class/access/spec.md
Normal file
55
cppdraft/class/access/spec.md
Normal 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.1 General [class.derived.general]") ([[class.derived]](class.derived "11.7 Derived classes")):
|
||||
|
||||
[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1 General [class.derived.general]") : [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]")opt
|
||||
|
||||
An[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1 General [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.1 General [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*]
|
||||
35
cppdraft/class/access/virt.md
Normal file
35
cppdraft/class/access/virt.md
Normal 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.8 Member 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
378
cppdraft/class/base/init.md
Normal 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.3 Initializing bases and members [class.base.init]"),
|
||||
which has the form
|
||||
|
||||
[ctor-initializer:](#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]")
|
||||
: [*mem-initializer-list*](#nt:mem-initializer-list "11.9.3 Initializing bases and members [class.base.init]")
|
||||
|
||||
[mem-initializer-list:](#nt:mem-initializer-list "11.9.3 Initializing bases and members [class.base.init]")
|
||||
[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") ...opt
|
||||
[*mem-initializer-list*](#nt:mem-initializer-list "11.9.3 Initializing bases and members [class.base.init]") , [*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") ...opt
|
||||
|
||||
[mem-initializer:](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]")
|
||||
[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
|
||||
[mem-initializer-id:](#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]")
|
||||
[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.3 Initializing 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.3 Initializing 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.3 Initializing 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.3 Initializing 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.3 Initializing 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.3 Initializing 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.1 General [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.3 Initializing 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.3 Initializing 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.3 Initializing 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.3 Initializing bases and members [class.base.init]") specifies more than one[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") for the same member or for the same base class,
|
||||
the[*ctor-initializer*](#nt:ctor-initializer "11.9.3 Initializing 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.3 Initializing 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.1 General [class.derived.general]") that denotes the constructor's class itself[.](#6.sentence-1)
|
||||
|
||||
If a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]") designates the constructor's class,
|
||||
it shall be the only [*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]"); the constructor
|
||||
is a [*delegating constructor*](#def:constructor,delegating "11.9.3 Initializing bases and members [class.base.init]"), and the constructor selected by the[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") is the [*target constructor*](#def:constructor,target "11.9.3 Initializing 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.1 General [expr.post.general]") or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") in a[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.5 Initializers") 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.3 Initializing bases and members [class.base.init]") constitutes a full-expression ([[intro.execution]](intro.execution "6.10.1 Sequential execution"))[.](#7.sentence-2)
|
||||
|
||||
Any expression in
|
||||
a[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.3 Initializing bases and members [class.base.init]") where the [*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing 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.3 Initializing 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.3 Copy/move constructors")),
|
||||
if a given potentially constructed subobject is not designated by a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]") (including the case where there is no[*mem-initializer-list*](#nt:mem-initializer-list "11.9.3 Initializing bases and members [class.base.init]") because the constructor has no[*ctor-initializer*](#nt:ctor-initializer "11.9.3 Initializing 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.4 Class members")) and either
|
||||
* [(9.1.1)](#9.1.1)
|
||||
|
||||
the constructor's class is a union ([[class.union]](class.union "11.5 Unions")), and no other variant
|
||||
member of that union is designated by a [*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing 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.3 Initializing bases and members [class.base.init]"),
|
||||
|
||||
the entity is initialized from its default member initializer
|
||||
as specified in [[dcl.init]](dcl.init "9.5 Initializers");
|
||||
|
||||
- [(9.2)](#9.2)
|
||||
|
||||
otherwise, if the entity is an anonymous union or a variant member ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions")), no initialization is performed;
|
||||
|
||||
- [(9.3)](#9.3)
|
||||
|
||||
otherwise, the entity is default-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#9.sentence-1)
|
||||
|
||||
[*Note [3](#note-3)*:
|
||||
|
||||
An abstract class ([[class.abstract]](class.abstract "11.7.4 Abstract 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.3 Initializing 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.4 Compound 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.5 Indeterminate 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.3 Initializing bases and members [class.base.init]"), the initialization specified by the[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.7 Destructors"))[.](#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.3 Stack 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.2 Object 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.1 General [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.1 General [class.derived.general]") (regardless of the order of the[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.3 Initializing 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.4 Compound 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.1 General [expr.post.general]") or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") of a [*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.3 Virtual 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.8 Type identification")) or of adynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic 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.3 Initializing bases and members [class.base.init]") (or in a function called directly or indirectly from a[*ctor-initializer*](#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]"))
|
||||
before all the[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.1 General")),
|
||||
|
||||
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.5 Construction 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.3 Initializing bases and members [class.base.init]") followed by an ellipsis is
|
||||
a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.1 General [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
116
cppdraft/class/bit.md
Normal 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.1 General [class.mem.general]") of the form
|
||||
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt : [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [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.1 Attribute 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.7 Constant 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.1 General [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.1 General"))[.](#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.11 Identifiers [lex.name]") declares an [*unnamed bit-field*](#def:bit-field,unnamed "11.4.10 Bit-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.4 References"))[.](#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.4 References")[.](#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.1 Enumeration 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
150
cppdraft/class/cdtor.md
Normal 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.3 Virtual functions")), can be called
|
||||
during construction or destruction ([[class.base.init]](class.base.init "11.9.3 Initializing 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.1 General")),
|
||||
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.5 Class 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.8 Type identification")) can be used during construction or destruction ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#5.sentence-1)
|
||||
|
||||
Whentypeid is used in a constructor (including the[*mem-initializer*](class.base.init#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") or default member initializer ([[class.mem]](class.mem "11.4 Class 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.7 Dynamic cast")) can be used during construction
|
||||
or destruction ([[class.base.init]](class.base.init "11.9.3 Initializing 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.3 Initializing 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
336
cppdraft/class/compare.md
Normal 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.3 Binary 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.2 Explicitly-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.1 General [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.2 Anonymous 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.1 Defaulted 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.2 Overload 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.1 General [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.1 General [class.mem.general]"),
|
||||
with the same access and [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [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.1 General [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.6 Functions [dcl.fct]") and
|
||||
trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.5 Exception specifications [except.spec]"),
|
||||
the implicitly-declared == operator function
|
||||
has an implicit exception specification ([[except.spec]](except.spec "14.5 Exception 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.1 General [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.1 General [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.2 Implicit conversion sequences")),
|
||||
class member access expressions ([[expr.ref]](expr.ref "7.6.1.5 Class member access")), and
|
||||
array subscript expressions ([[expr.sub]](expr.sub "7.6.1.2 Subscripting")) 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.3 Binary 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.1 Defaulted 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.3 Three-way comparison [class.spaceship]") of type R ([[cmp.categories]](cmp.categories "17.12.2 Comparison 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.1 Defaulted 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.1 Preamble")) 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.3 Three-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.2 Class 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.3 Class 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.4 Class 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.4 Secondary comparison operators [class.compare.secondary]") is
|
||||
a relational operator ([[expr.rel]](expr.rel "7.6.9 Relational operators")) or the != operator[.](#secondary-1.sentence-1)
|
||||
|
||||
A defaulted operator function ([[over.binary]](over.binary "12.4.3 Binary 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.2 Overload 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.3 Operators 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*]
|
||||
135
cppdraft/class/compare/default.md
Normal file
135
cppdraft/class/compare/default.md
Normal 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.3 Binary 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.2 Explicitly-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.1 General [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.2 Anonymous 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.1 Defaulted 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.2 Overload 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.1 General [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.1 General [class.mem.general]"),
|
||||
with the same access and [*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [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.1 General [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.6 Functions [dcl.fct]") and
|
||||
trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.5 Exception specifications [except.spec]"),
|
||||
the implicitly-declared == operator function
|
||||
has an implicit exception specification ([[except.spec]](except.spec "14.5 Exception 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.1 General [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.1 General [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.2 Implicit conversion sequences")),
|
||||
class member access expressions ([[expr.ref]](expr.ref "7.6.1.5 Class member access")), and
|
||||
array subscript expressions ([[expr.sub]](expr.sub "7.6.1.2 Subscripting")) applied to x[.](#5.sentence-3)
|
||||
60
cppdraft/class/compare/secondary.md
Normal file
60
cppdraft/class/compare/secondary.md
Normal 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.4 Secondary comparison operators [class.compare.secondary]") is
|
||||
a relational operator ([[expr.rel]](expr.rel "7.6.9 Relational operators")) or the != operator[.](#1.sentence-1)
|
||||
|
||||
A defaulted operator function ([[over.binary]](over.binary "12.4.3 Binary 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.2 Overload 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.3 Operators 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
254
cppdraft/class/conv.md
Normal 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.1 General [class.conv.general]") and are used for implicit type conversions ([[conv]](conv "7.3 Standard conversions")),
|
||||
for initialization ([[dcl.init]](dcl.init "9.5 Initializers")),
|
||||
and for explicit type conversions ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static 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.2 Member name lookup"), [[class.conv.fct]](#fct "11.4.8.3 Conversion functions"))[.](#general-2.sentence-1)
|
||||
|
||||
Conversions obey the access control rules ([[class.access]](class.access "11.8 Member access control"))[.](#general-2.sentence-2)
|
||||
|
||||
Access control is applied after ambiguity resolution ([[basic.lookup]](basic.lookup "6.5 Name 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.2 Overload 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.3 Function 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.5 Initializers"))
|
||||
or where casts ([[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)")) are explicitly
|
||||
used; see also [[over.match.copy]](over.match.copy "12.2.2.5 Copy-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.5 Initializers"))[.](#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.3 Conversion functions [class.conv.fct]")
|
||||
operator [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]")
|
||||
|
||||
[conversion-type-id:](#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]")
|
||||
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") [*conversion-declarator*](#nt:conversion-declarator "11.4.8.3 Conversion functions [class.conv.fct]")opt
|
||||
|
||||
[conversion-declarator:](#nt:conversion-declarator "11.4.8.3 Conversion functions [class.conv.fct]")
|
||||
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1 General [dcl.decl.general]") [*conversion-declarator*](#nt:conversion-declarator "11.4.8.3 Conversion 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.1 General [dcl.decl.general]") has
|
||||
an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") that is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") declares a [*conversion function*](#def:function,conversion "11.4.8.3 Conversion functions [class.conv.fct]");
|
||||
its [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") shall be
|
||||
a function declarator ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of the form
|
||||
|
||||
[*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]")
|
||||
|
||||
where the [*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") consists solely of
|
||||
an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]"),
|
||||
an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"), and
|
||||
optional surrounding parentheses, and
|
||||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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.1 General [class.mem.general]") that belongs to
|
||||
the [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of a class or class template
|
||||
but is not a friend declaration ([[class.friend]](class.friend "11.8.4 Friends")),
|
||||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]");
|
||||
|
||||
- [(1.2)](#fct-1.2)
|
||||
|
||||
otherwise, the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") whose [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3 Conversion 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.3 Conversion 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.3 Conversion functions [class.conv.fct]"),
|
||||
interpreted as a [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ([[dcl.name]](dcl.name "9.3.2 Type names"))[.](#fct-2.sentence-1)
|
||||
|
||||
A [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [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.1 General [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.3 Function specifiers")), in which case it is only considered as a user-defined conversion for direct-initialization ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#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.3 Conversion 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.3 Conversion functions [class.conv.fct]") in a[*conversion-function-id*](#nt:conversion-function-id "11.4.8.3 Conversion 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.3 Conversion 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.2 Member 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.4 Best 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.7 Placeholder 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*]
|
||||
49
cppdraft/class/conv/ctor.md
Normal file
49
cppdraft/class/conv/ctor.md
Normal 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.3 Function 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.5 Initializers"))
|
||||
or where casts ([[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)")) are explicitly
|
||||
used; see also [[over.match.copy]](over.match.copy "12.2.2.5 Copy-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.5 Initializers"))[.](#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
166
cppdraft/class/conv/fct.md
Normal 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.3 Conversion functions [class.conv.fct]")
|
||||
operator [*conversion-type-id*](#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]")
|
||||
|
||||
[conversion-type-id:](#nt:conversion-type-id "11.4.8.3 Conversion functions [class.conv.fct]")
|
||||
[*type-specifier-seq*](dcl.type.general#nt:type-specifier-seq "9.2.9.1 General [dcl.type.general]") [*conversion-declarator*](#nt:conversion-declarator "11.4.8.3 Conversion functions [class.conv.fct]")opt
|
||||
|
||||
[conversion-declarator:](#nt:conversion-declarator "11.4.8.3 Conversion functions [class.conv.fct]")
|
||||
[*ptr-operator*](dcl.decl.general#nt:ptr-operator "9.3.1 General [dcl.decl.general]") [*conversion-declarator*](#nt:conversion-declarator "11.4.8.3 Conversion 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.1 General [dcl.decl.general]") has
|
||||
an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") that is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]") declares a [*conversion function*](#def:function,conversion "11.4.8.3 Conversion functions [class.conv.fct]");
|
||||
its [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") shall be
|
||||
a function declarator ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of the form
|
||||
|
||||
[*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") [*parameters-and-qualifiers*](dcl.decl.general#nt:parameters-and-qualifiers "9.3.1 General [dcl.decl.general]")
|
||||
|
||||
where the [*noptr-declarator*](dcl.decl.general#nt:noptr-declarator "9.3.1 General [dcl.decl.general]") consists solely of
|
||||
an [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]"),
|
||||
an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"), and
|
||||
optional surrounding parentheses, and
|
||||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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.1 General [class.mem.general]") that belongs to
|
||||
the [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of a class or class template
|
||||
but is not a friend declaration ([[class.friend]](class.friend "11.8.4 Friends")),
|
||||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3 Conversion functions [class.conv.fct]");
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
otherwise, the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") whose [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") is a [*conversion-function-id*](#nt:conversion-function-id "11.4.8.3 Conversion 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.3 Conversion 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.3 Conversion functions [class.conv.fct]"),
|
||||
interpreted as a [*type-id*](dcl.name#nt:type-id "9.3.2 Type names [dcl.name]") ([[dcl.name]](dcl.name "9.3.2 Type names"))[.](#2.sentence-1)
|
||||
|
||||
A [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") in the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [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.1 General [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.3 Function specifiers")), in which case it is only considered as a user-defined conversion for direct-initialization ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#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.3 Conversion 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.3 Conversion functions [class.conv.fct]") in a[*conversion-function-id*](#nt:conversion-function-id "11.4.8.3 Conversion 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.3 Conversion 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.2 Member 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.4 Best 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.7 Placeholder 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*]
|
||||
53
cppdraft/class/conv/general.md
Normal file
53
cppdraft/class/conv/general.md
Normal 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.1 General [class.conv.general]") and are used for implicit type conversions ([[conv]](conv "7.3 Standard conversions")),
|
||||
for initialization ([[dcl.init]](dcl.init "9.5 Initializers")),
|
||||
and for explicit type conversions ([[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static 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.2 Member name lookup"), [[class.conv.fct]](class.conv.fct "11.4.8.3 Conversion functions"))[.](#2.sentence-1)
|
||||
|
||||
Conversions obey the access control rules ([[class.access]](class.access "11.8 Member access control"))[.](#2.sentence-2)
|
||||
|
||||
Access control is applied after ambiguity resolution ([[basic.lookup]](basic.lookup "6.5 Name 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.2 Overload 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*]
|
||||
309
cppdraft/class/copy/assign.md
Normal file
309
cppdraft/class/copy/assign.md
Normal 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.6 Copy/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.6 Function 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.6 Implicit 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.2 Overload 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.1 General")) 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.2 Overload resolution"), [[over.over]](over.over "12.3 Address 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.2 Simple assignment"))[.](#8.sentence-1)
|
||||
|
||||
[*Note [5](#note-5)*:
|
||||
|
||||
A [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The 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.3 Virtual functions"))
|
||||
and no virtual base classes ([[class.mi]](class.mi "11.7.2 Multiple 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.6 Copy/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.2 Explicitly-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.5 Exception 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.1 General [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.1 General")) 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.2 Object 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
301
cppdraft/class/copy/ctor.md
Normal 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.7 Default 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.7 Default 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.3 Copy/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.6 Function 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.6 Implicit 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.3 Deleted 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.2 Overload 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.1 General")) 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.2 Overload resolution"), [[over.over]](over.over "12.3 Address 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.3 Virtual functions"))
|
||||
and no virtual base classes ([[class.mi]](class.mi "11.7.2 Multiple 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.3 Copy/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.3 One-definition rule"), [[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#12.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
If an implicitly-defined ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2 Explicitly-defaulted functions")) constructor would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6 The 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.5 Exception 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.3 Initializing 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.3 Initializing 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.1 General")) of X[.](#15.sentence-1)
|
||||
|
||||
For each object nested within ([[intro.object]](intro.object "6.8.2 Object 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)
|
||||
145
cppdraft/class/copy/elision.md
Normal file
145
cppdraft/class/copy/elision.md
Normal 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.4 The return statement")) in
|
||||
a function with a class return type,
|
||||
when the [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.1 Preamble [except.pre]") of a[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ([[except.handle]](except.handle "14.4 Handling 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.18 Throwing an exception [expr.throw]") ([[expr.throw]](expr.throw "7.6.18 Throwing 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.1 Preamble [except.pre]") of a [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]"))
|
||||
that belongs to a scope that does not contain
|
||||
the innermost enclosing [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") associated with a [*try-block*](except.pre#nt:try-block "14.1 Preamble [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.4 Coroutine 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.1 Preamble [except.pre]") of a[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ([[except.handle]](except.handle "14.4 Handling 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.1 Preamble [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.1 Preamble [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.7 Constant expressions"))
|
||||
and in constant initialization ([[basic.start.static]](basic.start.static "6.10.3.2 Static 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.7 Constant 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
581
cppdraft/class/ctor.md
Normal 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.1 General [dcl.decl.general]") declares a [*constructor*](#def:constructor "11.4.5.1 General [class.ctor.general]") if it is a
|
||||
function declarator ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of the form
|
||||
|
||||
[*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1 General [dcl.decl.general]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
where the [*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1 General [dcl.decl.general]") consists solely of an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]"), an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"),
|
||||
and optional surrounding parentheses, and the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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.4 Friends")),
|
||||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") that names a constructor ([[class.qual]](class.qual "6.5.5.2 Class members"));
|
||||
|
||||
- [(1.2)](#general-1.2)
|
||||
|
||||
otherwise, in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") that belongs to the[*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of a class or class template,
|
||||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is the
|
||||
injected-class-name ([[class.pre]](class.pre "11.1 Preamble")) of the immediately-enclosing entity;
|
||||
|
||||
- [(1.3)](#general-1.3)
|
||||
|
||||
otherwise, the[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") whose [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified 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.1 General [dcl.spec.general]") in the optional[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") shall befriend,inline,constexpr,consteval, or
|
||||
an [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function 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.4 Explicit 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.9 Initialization")[.](#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.7 Temporary 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.1 Value 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.3 Initializing bases and members") and [[class.cdtor]](class.cdtor "11.9.5 Construction 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.2 The 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.2 Object 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.4 The 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.6 Functions"))[.](#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.2 Default 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.6 Function 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.4 Class 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.1 General [dcl.init.general]") is not const-default-constructible ([[dcl.init]](dcl.init "9.5 Initializers")),
|
||||
|
||||
- [(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.1 General [dcl.init.general]"),
|
||||
has class type M (or possibly multidimensional array thereof)
|
||||
and overload resolution ([[over.match]](over.match "12.2 Overload resolution"))
|
||||
as applied to find M's corresponding constructor
|
||||
does not result in a usable candidate ([[over.match.general]](over.match.general "12.2.1 General")), 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.2 Default 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.3 Virtual functions")) and no virtual base
|
||||
classes ([[class.mi]](class.mi "11.7.2 Multiple 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.4 Class 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.2 Default 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.1 General")),
|
||||
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.2 Explicitly-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.3 Initializing bases and members [class.base.init]") ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")) and an empty[*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound 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.6 The 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.5 Exception 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.6 Function 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.1 General"))[.](#class.default.ctor-5.sentence-1)
|
||||
|
||||
Such a default constructor needs to be accessible ([[class.access]](class.access "11.8 Member 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.3 Initializing 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.7 Default 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.7 Default 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.3 Copy/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.6 Function 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.6 Implicit 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.3 Deleted 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.2 Overload 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.1 General")) 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.2 Overload resolution"), [[over.over]](over.over "12.3 Address 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.3 Virtual functions"))
|
||||
and no virtual base classes ([[class.mi]](class.mi "11.7.2 Multiple 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.3 Copy/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.3 One-definition rule"), [[class.temporary]](class.temporary "6.8.7 Temporary objects"))[.](#class.copy.ctor-12.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
|
||||
If an implicitly-defined ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2 Explicitly-defaulted functions")) constructor would be constexpr-suitable ([[dcl.constexpr]](dcl.constexpr "9.2.6 The 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.5 Exception 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.3 Initializing 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.3 Initializing 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.1 General")) of X[.](#class.copy.ctor-15.sentence-1)
|
||||
|
||||
For each object nested within ([[intro.object]](intro.object "6.8.2 Object 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)
|
||||
138
cppdraft/class/ctor/general.md
Normal file
138
cppdraft/class/ctor/general.md
Normal 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.1 General [dcl.decl.general]") declares a [*constructor*](#def:constructor "11.4.5.1 General [class.ctor.general]") if it is a
|
||||
function declarator ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of the form
|
||||
|
||||
[*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1 General [dcl.decl.general]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
where the [*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1 General [dcl.decl.general]") consists solely of an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]"), an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"),
|
||||
and optional surrounding parentheses, and the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") has
|
||||
one of the following forms:
|
||||
|
||||
- [(1.1)](#1.1)
|
||||
|
||||
in a friend declaration ([[class.friend]](class.friend "11.8.4 Friends")),
|
||||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") that names a constructor ([[class.qual]](class.qual "6.5.5.2 Class members"));
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
otherwise, in a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") that belongs to the[*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of a class or class template,
|
||||
the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is the
|
||||
injected-class-name ([[class.pre]](class.pre "11.1 Preamble")) of the immediately-enclosing entity;
|
||||
|
||||
- [(1.3)](#1.3)
|
||||
|
||||
otherwise, the[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") whose [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified 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.1 General [dcl.spec.general]") in the optional[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]") shall befriend,inline,constexpr,consteval, or
|
||||
an [*explicit-specifier*](dcl.fct.spec#nt:explicit-specifier "9.2.3 Function 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.4 Explicit 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.9 Initialization")[.](#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.7 Temporary 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.1 Value 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.3 Initializing bases and members") and [[class.cdtor]](class.cdtor "11.9.5 Construction 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.2 The 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.2 Object 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.4 The 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.6 Functions"))[.](#8.sentence-1)
|
||||
156
cppdraft/class/default/ctor.md
Normal file
156
cppdraft/class/default/ctor.md
Normal 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.2 Default 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.6 Function 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.4 Class 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.1 General [dcl.init.general]") is not const-default-constructible ([[dcl.init]](dcl.init "9.5 Initializers")),
|
||||
|
||||
- [(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.1 General [dcl.init.general]"),
|
||||
has class type M (or possibly multidimensional array thereof)
|
||||
and overload resolution ([[over.match]](over.match "12.2 Overload resolution"))
|
||||
as applied to find M's corresponding constructor
|
||||
does not result in a usable candidate ([[over.match.general]](over.match.general "12.2.1 General")), 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.2 Default 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.3 Virtual functions")) and no virtual base
|
||||
classes ([[class.mi]](class.mi "11.7.2 Multiple base classes")), and
|
||||
|
||||
- [(3.2)](#3.2)
|
||||
|
||||
no non-static data member of X has
|
||||
a default member initializer ([[class.mem]](class.mem "11.4 Class 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.2 Default 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.1 General")),
|
||||
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.2 Explicitly-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.3 Initializing bases and members [class.base.init]") ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members")) and an empty[*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound 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.6 The 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.5 Exception specifications"))[.](#4.sentence-7)
|
||||
|
||||
An explicitly-defaulted definition might have an
|
||||
implicit exception specification, see [[dcl.fct.def]](dcl.fct.def "9.6 Function 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.1 General"))[.](#5.sentence-1)
|
||||
|
||||
Such a default constructor needs to be accessible ([[class.access]](class.access "11.8 Member 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.3 Initializing 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
763
cppdraft/class/derived.md
Normal 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.1 General [class.derived.general]")
|
||||
: [*base-specifier-list*](#nt:base-specifier-list "11.7.1 General [class.derived.general]")
|
||||
|
||||
[base-specifier-list:](#nt:base-specifier-list "11.7.1 General [class.derived.general]")
|
||||
[*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]") ...opt
|
||||
[*base-specifier-list*](#nt:base-specifier-list "11.7.1 General [class.derived.general]") , [*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]") ...opt
|
||||
|
||||
[base-specifier:](#nt:base-specifier "11.7.1 General [class.derived.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt virtual [*access-specifier*](#nt:access-specifier "11.7.1 General [class.derived.general]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*access-specifier*](#nt:access-specifier "11.7.1 General [class.derived.general]") virtualopt [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||||
|
||||
[class-or-decltype:](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||||
|
||||
[access-specifier:](#nt:access-specifier "11.7.1 General [class.derived.general]")
|
||||
private
|
||||
protected
|
||||
public
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to the [*base-specifier*](#nt:base-specifier "11.7.1 General [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.1 General [class.derived.general]") are those of its[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]"), and/or[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#general-2.sentence-1)
|
||||
|
||||
A [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]") shall denote
|
||||
a (possibly cv-qualified) class type that is not
|
||||
an incompletely defined class ([[class.mem]](class.mem "11.4 Class members"));
|
||||
any cv-qualifiers are ignored[.](#general-2.sentence-2)
|
||||
|
||||
The class denoted by the [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]") of
|
||||
a [*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]") is called a[*direct base class*](#def:base_class,direct "11.7.1 General [class.derived.general]") for the class being defined;
|
||||
for each such [*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]"),
|
||||
the corresponding [*direct base class relationship*](#def:relationship,direct_base_class "11.7.1 General [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.3 Simple type specifiers [dcl.type.simple]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") is type-only ([[basic.lookup]](basic.lookup "6.5 Name 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.1 General [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.8 Member access control") for the meaning of[*access-specifier*](#nt:access-specifier "11.7.1 General [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.10 The 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.2 Member name lookup"))[.](#general-2.sentence-11)
|
||||
|
||||
The scope resolution operator :: ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified 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.3 Accessibility 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.12 Pointer 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.4 References"))[.](#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.1 General [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.1 General [class.derived.general]") followed by an ellipsis is a pack
|
||||
expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.2 Object 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*]
|
||||
|
||||

|
||||
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.3 Initializing 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.5 Construction 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.2 Object 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.3 Initializing bases and members")),
|
||||
cleanup ([[class.dtor]](class.dtor "11.4.7 Destructors")), and storage
|
||||
layout ([[class.mem]](class.mem "11.4 Class members"), [[class.access.spec]](class.access.spec "11.8.2 Access 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.2 Multiple 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.2 Multiple 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.2 Object 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)
|
||||
|
||||

|
||||
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.2 Member 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 { /* ... */ };
|
||||
|
||||

|
||||
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)
|
||||
|
||||

|
||||
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.3 Virtual 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.3 Virtual 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.1 General")) to a declaration of F,
|
||||
ignoring trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s*,
|
||||
then G [*overrides*](#def:function,virtual,override "11.7.3 Virtual 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.3 Virtual functions [class.virtual]") unless the most derived class ([[intro.object]](intro.object "6.8.2 Object 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.1 General [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.1 General [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.1 Preamble [temp.pre]") ([[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#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.3 Constrained 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.1 General [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.3 Virtual 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.2 Point 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.3 Function 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.3 Function 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.3 Function 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.4 Friends")) 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.4 Abstract classes")) in that class, or both; no diagnostic is
|
||||
required ([[basic.def.odr]](basic.def.odr "6.3 One-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.3 Qualified 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.6 Function 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 "12 Overloading"))
|
||||
as a virtual function is not necessarily virtual and
|
||||
does not override[.](#footnote-94.sentence-1)
|
||||
|
||||
Access control ([[class.access]](class.access "11.8 Member 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.4 Abstract classes [class.abstract]") by using a[*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1 General [class.mem.general]") ([[class.mem]](class.mem "11.4 Class 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.4 Abstract 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.2 Declarations and definitions"), [[class.mem]](class.mem "11.4 Class 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.7 Destructors")), the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") syntax ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified 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.1 General [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.6 Functions")) or called ([[expr.call]](expr.call "7.6.1.3 Function call")),
|
||||
except as specified in [[dcl.type.simple]](dcl.type.simple "9.2.9.3 Simple 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.9 Static cast"), [[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10 Reinterpret cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11 Const cast")),
|
||||
because the resulting prvalue would be of abstract class type ([[basic.lval]](basic.lval "7.2.1 Value 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.3 Virtual 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)
|
||||
179
cppdraft/class/derived/general.md
Normal file
179
cppdraft/class/derived/general.md
Normal 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.1 General [class.derived.general]")
|
||||
: [*base-specifier-list*](#nt:base-specifier-list "11.7.1 General [class.derived.general]")
|
||||
|
||||
[base-specifier-list:](#nt:base-specifier-list "11.7.1 General [class.derived.general]")
|
||||
[*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]") ...opt
|
||||
[*base-specifier-list*](#nt:base-specifier-list "11.7.1 General [class.derived.general]") , [*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]") ...opt
|
||||
|
||||
[base-specifier:](#nt:base-specifier "11.7.1 General [class.derived.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt virtual [*access-specifier*](#nt:access-specifier "11.7.1 General [class.derived.general]")opt [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*access-specifier*](#nt:access-specifier "11.7.1 General [class.derived.general]") virtualopt [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||||
|
||||
[class-or-decltype:](#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]") template [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
[*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||||
|
||||
[access-specifier:](#nt:access-specifier "11.7.1 General [class.derived.general]")
|
||||
private
|
||||
protected
|
||||
public
|
||||
|
||||
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") appertains to the [*base-specifier*](#nt:base-specifier "11.7.1 General [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.1 General [class.derived.general]") are those of its[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),[*type-name*](dcl.type.simple#nt:type-name "9.2.9.3 Simple type specifiers [dcl.type.simple]"), and/or[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")[.](#2.sentence-1)
|
||||
|
||||
A [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]") shall denote
|
||||
a (possibly cv-qualified) class type that is not
|
||||
an incompletely defined class ([[class.mem]](class.mem "11.4 Class members"));
|
||||
any cv-qualifiers are ignored[.](#2.sentence-2)
|
||||
|
||||
The class denoted by the [*class-or-decltype*](#nt:class-or-decltype "11.7.1 General [class.derived.general]") of
|
||||
a [*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]") is called a[*direct base class*](#def:base_class,direct "11.7.1 General [class.derived.general]") for the class being defined;
|
||||
for each such [*base-specifier*](#nt:base-specifier "11.7.1 General [class.derived.general]"),
|
||||
the corresponding [*direct base class relationship*](#def:relationship,direct_base_class "11.7.1 General [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.3 Simple type specifiers [dcl.type.simple]") or [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") is type-only ([[basic.lookup]](basic.lookup "6.5 Name 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.1 General [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.8 Member access control") for the meaning of[*access-specifier*](#nt:access-specifier "11.7.1 General [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.10 The 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.2 Member name lookup"))[.](#2.sentence-11)
|
||||
|
||||
The scope resolution operator :: ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified 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.3 Accessibility 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.12 Pointer 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.4 References"))[.](#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.1 General [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.1 General [class.derived.general]") followed by an ellipsis is a pack
|
||||
expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.2 Object 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*]
|
||||
|
||||

|
||||
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.3 Initializing 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.5 Construction 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.2 Object model"))[.](#7.sentence-3)
|
||||
|
||||
â *end note*]
|
||||
389
cppdraft/class/dtor.md
Normal file
389
cppdraft/class/dtor.md
Normal 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.1 General [dcl.decl.general]") has an [*unqualified-id*](expr.prim.id.unqual#nt:unqualified-id "7.5.5.2 Unqualified names [expr.prim.id.unqual]") that begins with a ~ declares a [*prospective destructor*](#def:destructor,prospective "11.4.7 Destructors [class.dtor]");
|
||||
its [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") shall be a function declarator ([[dcl.fct]](dcl.fct "9.3.4.6 Functions")) of the form
|
||||
|
||||
[*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1 General [dcl.decl.general]") ( [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [dcl.fct]") ) [*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt
|
||||
|
||||
where the [*ptr-declarator*](dcl.decl.general#nt:ptr-declarator "9.3.1 General [dcl.decl.general]") consists solely of an[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]"), an optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]"),
|
||||
and optional surrounding parentheses, and the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [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.1 General [class.mem.general]") that belongs to the[*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]") of a class or class template
|
||||
but is not a friend
|
||||
declaration ([[class.friend]](class.friend "11.8.4 Friends")), the [*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is~[*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") and the [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") is the
|
||||
injected-class-name ([[class.pre]](class.pre "11.1 Preamble")) of the immediately-enclosing entity or
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
otherwise, the[*id-expression*](expr.prim.id.general#nt:id-expression "7.5.5.1 General [expr.prim.id.general]") is [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")~[*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") and the [*class-name*](class.pre#nt:class-name "11.1 Preamble [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.3 Qualified names [expr.prim.id.qual]")[.](#1.sentence-1)
|
||||
|
||||
A prospective destructor shall take no arguments ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#1.sentence-2)
|
||||
|
||||
Each [*decl-specifier*](dcl.spec.general#nt:decl-specifier "9.2.1 General [dcl.spec.general]") of the [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [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.6 Function 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.7 Destructors [class.dtor]") for the class,
|
||||
also known as the [*selected destructor*](#def:destructor,selected "11.4.7 Destructors [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.3 One-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.3 Deleted 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.4 The 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.2 The 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.2 Object 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.5 Exception specifications [except.spec]") has the same exception specification as if it had been implicitly declared ([[except.spec]](except.spec "14.5 Exception 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.7 Destructors [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.6 The 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.3 Virtual functions"))
|
||||
and with a [*pure-specifier*](class.mem.general#nt:pure-specifier "11.4.1 General [class.mem.general]") ([[class.abstract]](class.abstract "11.7.4 Abstract 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.5 Construction 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.3 Initializing 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.3 Initializing bases and members"))[.](#13.sentence-3)
|
||||
|
||||
[*Note [4](#note-4)*:
|
||||
|
||||
Areturn statement ([[stmt.return]](stmt.return "8.8.4 The 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.9 Initialization"))[.](#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.2 Static storage duration")) at program termination ([[basic.start.term]](basic.start.term "6.10.3.4 Termination")),
|
||||
|
||||
- [(14.2)](#14.2)
|
||||
|
||||
for a constructed object with thread storage duration ([[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread 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.4 Automatic storage duration")) when the block in which an object is created exits ([[stmt.dcl]](stmt.dcl "8.10 Declaration statement")),
|
||||
|
||||
- [(14.4)](#14.4)
|
||||
|
||||
for a constructed temporary object when its lifetime ends ([[conv.rval]](conv.rval "7.3.5 Temporary materialization conversion"), [[class.temporary]](class.temporary "6.8.7 Temporary 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.9 Delete [expr.delete]") ([[expr.delete]](expr.delete "7.6.2.9 Delete")) for a constructed object allocated
|
||||
by a [*new-expression*](expr.new#nt:new-expression "7.6.2.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")); the context of the invocation is the[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [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.7 Destructors [class.dtor]") if it is invoked or as specified in [[expr.new]](expr.new "7.6.2.8 New"),[[stmt.return]](stmt.return "8.8.4 The return statement"), [[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates"),[[class.base.init]](class.base.init "11.9.3 Initializing bases and members"), and [[except.throw]](except.throw "14.2 Throwing 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.9 Delete"))[.](#15.sentence-1)
|
||||
|
||||
If the lookup fails or if the deallocation function has
|
||||
a deleted definition ([[dcl.fct.def]](dcl.fct.def "9.6 Function 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.9 Delete [expr.delete]") ([[class.free]](class.free "11.4.11 Allocation 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.3 Simple type specifiers [dcl.type.simple]") or [*computed-type-specifier*](dcl.type.simple#nt:computed-type-specifier "9.2.9.3 Simple 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.2 Member 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.9 Delete")[.](#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.5 Class member access")) or a [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3 Qualified names [expr.prim.id.qual]") ([[expr.prim.id.qual]](expr.prim.id.qual "7.5.5.3 Qualified names"));
|
||||
in particular, the[*unary-expression*](expr.unary.general#nt:unary-expression "7.6.2.1 General [expr.unary.general]")~X() in a member function is not an explicit destructor call ([[expr.unary.op]](expr.unary.op "7.6.2.2 Unary 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.8 New [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.4 Lifetime"))[.](#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.5 Destruction"))[.](#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
41
cppdraft/class/eq.md
Normal 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.3 Binary 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.1 Defaulted 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*]
|
||||
87
cppdraft/class/expl/init.md
Normal file
87
cppdraft/class/expl/init.md
Normal 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.1 General [expr.post.general]"),
|
||||
where the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [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.19 Assignment and compound assignment operators [expr.assign]") can be specified as an[*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.5 Initializers")[.](#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.2 Simple 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.1 General [dcl.init.general]")[.](#2.sentence-1)
|
||||
|
||||
List-initialization semantics apply;
|
||||
see [[dcl.init]](dcl.init "9.5 Initializers") and [[dcl.init.list]](dcl.init.list "9.5.5 List-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.1 General [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.2 Aggregates")[.](#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.1 General [dcl.init.general]") is explicitly specified (see [[class.init]](class.init "11.9 Initialization") and [[dcl.init]](dcl.init "9.5 Initializers"))[.](#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.3 Dynamic initialization of non-block variables") and [[stmt.dcl]](stmt.dcl "8.10 Declaration statement")[.](#4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
101
cppdraft/class/free.md
Normal file
101
cppdraft/class/free.md
Normal 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.3 Explicit type conversion (cast notation) [expr.cast]") of a[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [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.3 Explicit type conversion (cast notation) [expr.cast]") of a[*delete-expression*](expr.delete#nt:delete-expression "7.6.2.9 Delete [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.5 Exception specifications [except.spec]"), it
|
||||
has a non-throwing exception specification ([[except.spec]](except.spec "14.5 Exception specifications"))[.](#6.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
167
cppdraft/class/friend.md
Normal file
167
cppdraft/class/friend.md
Normal 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.1 General [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.1 General [class.mem.general]")[.](#3.sentence-1)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
A friend declaration can be the[*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") in
|
||||
a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") ([[temp.pre]](temp.pre "13.1 Preamble"), [[temp.friend]](temp.friend "13.7.5 Friends"))[.](#3.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
|
||||
If a [*friend-type-specifier*](class.mem.general#nt:friend-type-specifier "11.4.1 General [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.1 General [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.6 Local 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.8 The 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.2 Storage class specifiers [dcl.stc]") shall appear in the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [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.4 Class members"))
|
||||
portion of the class[*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [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.4 Meaning of declarators"), [[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated 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
157
cppdraft/class/gslice.md
Normal 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)
|
||||
115
cppdraft/class/gslice/overview.md
Normal file
115
cppdraft/class/gslice/overview.md
Normal 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)
|
||||
82
cppdraft/class/inhctor/init.md
Normal file
82
cppdraft/class/inhctor/init.md
Normal 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.10 The 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.3 Initializing 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
856
cppdraft/class/init.md
Normal 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.5 Initializers")[.](#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.2 Explicit initialization") and [[class.base.init]](#class.base.init "11.9.3 Initializing 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.5 Arrays")[.](#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.1 General [expr.post.general]"),
|
||||
where the[*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [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.19 Assignment and compound assignment operators [expr.assign]") can be specified as an[*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.5 Initializers")[.](#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.2 Simple 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.1 General [dcl.init.general]")[.](#class.expl.init-2.sentence-1)
|
||||
|
||||
List-initialization semantics apply;
|
||||
see [[dcl.init]](dcl.init "9.5 Initializers") and [[dcl.init.list]](dcl.init.list "9.5.5 List-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.1 General [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.2 Aggregates")[.](#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.1 General [dcl.init.general]") is explicitly specified (see [class.init] and [[dcl.init]](dcl.init "9.5 Initializers"))[.](#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.3 Dynamic initialization of non-block variables") and [[stmt.dcl]](stmt.dcl "8.10 Declaration 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.3 Initializing bases and members [class.base.init]"),
|
||||
which has the form
|
||||
|
||||
[ctor-initializer:](#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]")
|
||||
: [*mem-initializer-list*](#nt:mem-initializer-list "11.9.3 Initializing bases and members [class.base.init]")
|
||||
|
||||
[mem-initializer-list:](#nt:mem-initializer-list "11.9.3 Initializing bases and members [class.base.init]")
|
||||
[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") ...opt
|
||||
[*mem-initializer-list*](#nt:mem-initializer-list "11.9.3 Initializing bases and members [class.base.init]") , [*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") ...opt
|
||||
|
||||
[mem-initializer:](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]")
|
||||
[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]") ( [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [expr.post.general]")opt )
|
||||
[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]") [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]")
|
||||
|
||||
[mem-initializer-id:](#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]")
|
||||
[*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1 General [class.derived.general]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [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.3 Initializing 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.3 Initializing 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.3 Initializing 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.3 Initializing 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.3 Initializing 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.3 Initializing 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.1 General [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.3 Initializing 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.3 Initializing 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.3 Initializing 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.3 Initializing bases and members [class.base.init]") specifies more than one[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") for the same member or for the same base class,
|
||||
the[*ctor-initializer*](#nt:ctor-initializer "11.9.3 Initializing 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.3 Initializing 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.1 General [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.3 Initializing bases and members [class.base.init]") designates the constructor's class,
|
||||
it shall be the only [*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]"); the constructor
|
||||
is a [*delegating constructor*](#def:constructor,delegating "11.9.3 Initializing bases and members [class.base.init]"), and the constructor selected by the[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") is the [*target constructor*](#def:constructor,target "11.9.3 Initializing 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.1 General [expr.post.general]") or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") in a[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.5 Initializers") 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.3 Initializing bases and members [class.base.init]") constitutes a full-expression ([[intro.execution]](intro.execution "6.10.1 Sequential execution"))[.](#class.base.init-7.sentence-2)
|
||||
|
||||
Any expression in
|
||||
a[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.3 Initializing bases and members [class.base.init]") where the [*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing 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.3 Initializing 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.3 Copy/move constructors")),
|
||||
if a given potentially constructed subobject is not designated by a[*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing bases and members [class.base.init]") (including the case where there is no[*mem-initializer-list*](#nt:mem-initializer-list "11.9.3 Initializing bases and members [class.base.init]") because the constructor has no[*ctor-initializer*](#nt:ctor-initializer "11.9.3 Initializing 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.4 Class members")) and either
|
||||
* [(9.1.1)](#class.base.init-9.1.1)
|
||||
|
||||
the constructor's class is a union ([[class.union]](class.union "11.5 Unions")), and no other variant
|
||||
member of that union is designated by a [*mem-initializer-id*](#nt:mem-initializer-id "11.9.3 Initializing 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.3 Initializing bases and members [class.base.init]"),
|
||||
|
||||
the entity is initialized from its default member initializer
|
||||
as specified in [[dcl.init]](dcl.init "9.5 Initializers");
|
||||
|
||||
- [(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.2 Anonymous unions")), no initialization is performed;
|
||||
|
||||
- [(9.3)](#class.base.init-9.3)
|
||||
|
||||
otherwise, the entity is default-initialized ([[dcl.init]](dcl.init "9.5 Initializers"))[.](#class.base.init-9.sentence-1)
|
||||
|
||||
[*Note [3](#class.base.init-note-3)*:
|
||||
|
||||
An abstract class ([[class.abstract]](class.abstract "11.7.4 Abstract 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.3 Initializing 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.4 Compound 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.5 Indeterminate 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.3 Initializing bases and members [class.base.init]"), the initialization specified by the[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.7 Destructors"))[.](#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.3 Stack 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.2 Object 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.1 General [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.1 General [class.derived.general]") (regardless of the order of the[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.3 Initializing 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.4 Compound 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.1 General [expr.post.general]") or [*braced-init-list*](dcl.init.general#nt:braced-init-list "9.5.1 General [dcl.init.general]") of a [*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.3 Virtual 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.8 Type identification")) or of adynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic 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.3 Initializing bases and members [class.base.init]") (or in a function called directly or indirectly from a[*ctor-initializer*](#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]"))
|
||||
before all the[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing 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.1 General")),
|
||||
|
||||
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.5 Construction 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.3 Initializing bases and members [class.base.init]") followed by an ellipsis is
|
||||
a pack expansion ([[temp.variadic]](temp.variadic "13.7.4 Variadic 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.1 General [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.10 The 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.3 Initializing 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.3 Virtual functions")), can be called
|
||||
during construction or destruction ([[class.base.init]](#class.base.init "11.9.3 Initializing 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.1 General")),
|
||||
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.5 Class 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.8 Type identification")) can be used during construction or destruction ([[class.base.init]](#class.base.init "11.9.3 Initializing bases and members"))[.](#class.cdtor-5.sentence-1)
|
||||
|
||||
Whentypeid is used in a constructor (including the[*mem-initializer*](#nt:mem-initializer "11.9.3 Initializing bases and members [class.base.init]") or default member initializer ([[class.mem]](class.mem "11.4 Class 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.7 Dynamic cast")) can be used during construction
|
||||
or destruction ([[class.base.init]](#class.base.init "11.9.3 Initializing 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.3 Initializing 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.4 The return statement")) in
|
||||
a function with a class return type,
|
||||
when the [*expression*](expr.comma#nt:expression "7.6.20 Comma 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.1 Preamble [except.pre]") of a[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ([[except.handle]](except.handle "14.4 Handling 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.18 Throwing an exception [expr.throw]") ([[expr.throw]](expr.throw "7.6.18 Throwing 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.1 Preamble [except.pre]") of a [*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]"))
|
||||
that belongs to a scope that does not contain
|
||||
the innermost enclosing [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") associated with a [*try-block*](except.pre#nt:try-block "14.1 Preamble [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.4 Coroutine 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.1 Preamble [except.pre]") of a[*handler*](except.pre#nt:handler "14.1 Preamble [except.pre]") ([[except.handle]](except.handle "14.4 Handling 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.1 Preamble [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.1 Preamble [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.7 Constant expressions"))
|
||||
and in constant initialization ([[basic.start.static]](basic.start.static "6.10.3.2 Static 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.7 Constant 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*]
|
||||
39
cppdraft/class/init/general.md
Normal file
39
cppdraft/class/init/general.md
Normal 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.5 Initializers")[.](#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.2 Explicit initialization") and [[class.base.init]](class.base.init "11.9.3 Initializing 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.5 Arrays")[.](#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
56
cppdraft/class/local.md
Normal 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.6 Local 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.3 One-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.8 Member 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.3 Static data members"))[.](#4.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
2816
cppdraft/class/mem.md
Normal file
2816
cppdraft/class/mem.md
Normal file
File diff suppressed because it is too large
Load Diff
659
cppdraft/class/mem/general.md
Normal file
659
cppdraft/class/mem/general.md
Normal 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.1 General [class.mem.general]")
|
||||
[*member-declaration*](#nt:member-declaration "11.4.1 General [class.mem.general]") [*member-specification*](#nt:member-specification "11.4.1 General [class.mem.general]")opt
|
||||
[*access-specifier*](class.derived.general#nt:access-specifier "11.7.1 General [class.derived.general]") : [*member-specification*](#nt:member-specification "11.4.1 General [class.mem.general]")opt
|
||||
|
||||
[member-declaration:](#nt:member-declaration "11.4.1 General [class.mem.general]")
|
||||
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1 General [dcl.spec.general]")opt [*member-declarator-list*](#nt:member-declarator-list "11.4.1 General [class.mem.general]")opt ;
|
||||
[*function-definition*](dcl.fct.def.general#nt:function-definition "9.6.1 General [dcl.fct.def.general]")
|
||||
[*friend-type-declaration*](#nt:friend-type-declaration "11.4.1 General [class.mem.general]")
|
||||
[*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]")
|
||||
[*using-enum-declaration*](enum.udecl#nt:using-enum-declaration "9.8.2 The using enum declaration [enum.udecl]")
|
||||
[*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]")
|
||||
[*explicit-specialization*](temp.expl.spec#nt:explicit-specialization "13.9.4 Explicit specialization [temp.expl.spec]")
|
||||
[*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]")
|
||||
[*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]")
|
||||
[*opaque-enum-declaration*](dcl.enum#nt:opaque-enum-declaration "9.8.1 Enumeration declarations [dcl.enum]")
|
||||
[*empty-declaration*](dcl.pre#nt:empty-declaration "9.1 Preamble [dcl.pre]")
|
||||
|
||||
[member-declarator-list:](#nt:member-declarator-list "11.4.1 General [class.mem.general]")
|
||||
[*member-declarator*](#nt:member-declarator "11.4.1 General [class.mem.general]")
|
||||
[*member-declarator-list*](#nt:member-declarator-list "11.4.1 General [class.mem.general]") , [*member-declarator*](#nt:member-declarator "11.4.1 General [class.mem.general]")
|
||||
|
||||
[member-declarator:](#nt:member-declarator "11.4.1 General [class.mem.general]")
|
||||
[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") [*virt-specifier-seq*](#nt:virt-specifier-seq "11.4.1 General [class.mem.general]")opt [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt [*pure-specifier*](#nt:pure-specifier "11.4.1 General [class.mem.general]")opt
|
||||
[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]") [*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1 General [dcl.contract.func]")opt
|
||||
[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")opt [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt : [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")opt
|
||||
|
||||
[virt-specifier-seq:](#nt:virt-specifier-seq "11.4.1 General [class.mem.general]")
|
||||
[*virt-specifier*](#nt:virt-specifier "11.4.1 General [class.mem.general]") [*virt-specifier-seq*](#nt:virt-specifier-seq "11.4.1 General [class.mem.general]")opt
|
||||
|
||||
[virt-specifier:](#nt:virt-specifier "11.4.1 General [class.mem.general]")
|
||||
override
|
||||
final
|
||||
|
||||
[pure-specifier:](#nt:pure-specifier "11.4.1 General [class.mem.general]")
|
||||
= 0
|
||||
|
||||
[friend-type-declaration:](#nt:friend-type-declaration "11.4.1 General [class.mem.general]")
|
||||
friend [*friend-type-specifier-list*](#nt:friend-type-specifier-list "11.4.1 General [class.mem.general]") ;
|
||||
|
||||
[friend-type-specifier-list:](#nt:friend-type-specifier-list "11.4.1 General [class.mem.general]")
|
||||
[*friend-type-specifier*](#nt:friend-type-specifier "11.4.1 General [class.mem.general]") ...opt
|
||||
[*friend-type-specifier-list*](#nt:friend-type-specifier-list "11.4.1 General [class.mem.general]") , [*friend-type-specifier*](#nt:friend-type-specifier "11.4.1 General [class.mem.general]") ...opt
|
||||
|
||||
[friend-type-specifier:](#nt:friend-type-specifier "11.4.1 General [class.mem.general]")
|
||||
[*simple-type-specifier*](dcl.type.simple#nt:simple-type-specifier "9.2.9.3 Simple type specifiers [dcl.type.simple]")
|
||||
[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]")
|
||||
[*typename-specifier*](temp.res.general#nt:typename-specifier "13.8.1 General [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.1 General [class.mem.general]"),
|
||||
the token sequence = 0 is treated as a [*pure-specifier*](#nt:pure-specifier "11.4.1 General [class.mem.general]") if the type of the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [dcl.decl.general]") ([[dcl.meaning.general]](dcl.meaning.general "9.3.4.1 General"))
|
||||
is a function type, and
|
||||
is otherwise treated as a [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [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.1 General")[.](#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.1 General [dcl.contract.func]") ([[dcl.contract.func]](dcl.contract.func "9.4.1 General"))
|
||||
in a [*member-declarator*](#nt:member-declarator "11.4.1 General [class.mem.general]") shall be present only if
|
||||
the [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [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.1 General [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.1 General [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.1 General [class.mem.general]") of X,
|
||||
including anonymous union members ([[class.union.anon]](class.union.anon "11.5.2 Anonymous unions")) and direct members thereof[.](#3.sentence-2)
|
||||
|
||||
Members of a class are data members, member
|
||||
functions ([[class.mfct]](class.mfct "11.4.2 Member functions")), nested types, enumerators,
|
||||
and member templates ([[temp.mem]](temp.mem "13.7.3 Member 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.1 General [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.4 Friends")),
|
||||
|
||||
- [(4.2)](#4.2)
|
||||
|
||||
a [*deduction-guide*](temp.deduct.guide#nt:deduction-guide "13.7.2.3 Deduction guides [temp.deduct.guide]") ([[temp.deduct.guide]](temp.deduct.guide "13.7.2.3 Deduction guides")),
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
a [*template-declaration*](temp.pre#nt:template-declaration "13.1 Preamble [temp.pre]") whose [*declaration*](dcl.pre#nt:declaration "9.1 Preamble [dcl.pre]") is one of the above,
|
||||
|
||||
- [(4.4)](#4.4)
|
||||
|
||||
a [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]"),
|
||||
|
||||
- [(4.5)](#4.5)
|
||||
|
||||
a [*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]"),
|
||||
|
||||
- [(4.6)](#4.6)
|
||||
|
||||
a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The using declaration")), or
|
||||
|
||||
- [(4.7)](#4.7)
|
||||
|
||||
an [*empty-declaration*](dcl.pre#nt:empty-declaration "9.1 Preamble [dcl.pre]")[.](#4.sentence-1)
|
||||
|
||||
For any other [*member-declaration*](#nt:member-declaration "11.4.1 General [class.mem.general]"),
|
||||
each declared entity
|
||||
that is not an [unnamed bit-field](class.bit#def:bit-field,unnamed "11.4.10 Bit-fields [class.bit]") is a member of the class,
|
||||
and each such [*member-declaration*](#nt:member-declaration "11.4.1 General [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.1 General [class.mem.general]") is a non-function member introduced by a[*member-declarator*](#nt:member-declarator "11.4.1 General [class.mem.general]")[.](#5.sentence-1)
|
||||
|
||||
A [*member function*](#def:member_function "11.4.1 General [class.mem.general]") is a member that is a function[.](#5.sentence-2)
|
||||
|
||||
Nested types are classes ([[class.name]](class.name "11.3 Class names"), [[class.nest]](class.nest "11.4.12 Nested class declarations")) and
|
||||
enumerations ([[dcl.enum]](dcl.enum "9.8.1 Enumeration declarations")) declared in the class and arbitrary types
|
||||
declared as members by use of a typedef declaration ([[dcl.typedef]](dcl.typedef "9.2.4 The typedef specifier"))
|
||||
or [*alias-declaration*](dcl.pre#nt:alias-declaration "9.1 Preamble [dcl.pre]")[.](#5.sentence-3)
|
||||
|
||||
The enumerators of an [unscoped enumeration](dcl.enum "9.8.1 Enumeration 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.1 General [class.mem.general]"),
|
||||
in which case it is a [*static member*](#def:member,static "11.4.1 General [class.mem.general]") (see [[class.static]](class.static "11.4.9 Static members"))
|
||||
(a [*static data member*](#def:data_member,static "11.4.1 General [class.mem.general]") ([[class.static.data]](class.static.data "11.4.9.3 Static data members")) or[*static member function*](#def:member_function,static "11.4.1 General [class.mem.general]") ([[class.static.mfct]](class.static.mfct "11.4.9.2 Static 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.1 General [class.mem.general]") (a [*non-static data member*](#def:data_member,non-static "11.4.1 General [class.mem.general]") or[*non-static member function*](#def:member_function,non-static "11.4.1 General [class.mem.general]") ([[class.mfct.non.static]](class.mfct.non.static "11.4.3 Non-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.1 General [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.1 Enumeration declarations [dcl.enum]") and later
|
||||
redeclared with an [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration 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.1 General"))[.](#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.4 Explicit specialization"), [[temp.explicit]](temp.explicit "13.9.3 Explicit 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.1 General [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.1 General")),
|
||||
|
||||
- [(10.2)](#10.2)
|
||||
|
||||
default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments")),
|
||||
|
||||
- [(10.3)](#10.3)
|
||||
|
||||
default template argument ([[temp.param]](temp.param "13.2 Template parameters")),
|
||||
|
||||
- [(10.4)](#10.4)
|
||||
|
||||
[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5 Exception specifications [except.spec]") ([[except.spec]](except.spec "14.5 Exception specifications")),
|
||||
|
||||
- [(10.5)](#10.5)
|
||||
|
||||
[*function-contract-specifier*](dcl.contract.func#nt:function-contract-specifier "9.4.1 General [dcl.contract.func]") ([[dcl.contract.func]](dcl.contract.func "9.4.1 General")), or
|
||||
|
||||
- [(10.6)](#10.6)
|
||||
|
||||
default member initializer
|
||||
|
||||
within the [*member-specification*](#nt:member-specification "11.4.1 General [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.1 General [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.7 Reachability"))
|
||||
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.1 General [class.mem.general]") matches
|
||||
the syntactic requirements of [*friend-type-declaration*](#nt:friend-type-declaration "11.4.1 General [class.mem.general]"),
|
||||
it is a [*friend-type-declaration*](#nt:friend-type-declaration "11.4.1 General [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.1 General [class.mem.general]"),
|
||||
an = immediately following the [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") is interpreted as introducing a [*pure-specifier*](#nt:pure-specifier "11.4.1 General [class.mem.general]") if the [*declarator-id*](dcl.decl.general#nt:declarator-id "9.3.1 General [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.1 General [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.1 General [dcl.init.general]")virtual T f = 0; // OK, [*pure-specifier*](#nt:pure-specifier "11.4.1 General [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.1 General [class.mem.general]") for a bit-field,
|
||||
the [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant expressions [expr.const]") is parsed as
|
||||
the longest sequence of tokens
|
||||
that could syntactically form a [*constant-expression*](expr.const#nt:constant-expression "7.7 Constant 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.1 General [dcl.init.general]")int x2 : 8 { 42 }; // OK, "{ 42 }" is [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]")int y1 : true ? 8 : a = 42; // OK, [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [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.1 General [dcl.init.general]")int z : 1 || new int { 0 }; // OK, [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [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.1 General [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.3 Static data members"); for non-static data members,
|
||||
see [[class.base.init]](class.base.init "11.9.3 Initializing bases and members") and [[dcl.init.aggr]](dcl.init.aggr "9.5.2 Aggregates"))[.](#15.sentence-2)
|
||||
|
||||
A [*brace-or-equal-initializer*](dcl.init.general#nt:brace-or-equal-initializer "9.5.1 General [dcl.init.general]") for a non-static data memberspecifies a [*default member initializer*](#def:default_member_initializer "11.4.1 General [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.7 Constant expressions")) that
|
||||
is a potentially-evaluated subexpression ([[intro.execution]](intro.execution "6.10.1 Sequential 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.2 Storage 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.2 Storage 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.1 General [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.1 General [dcl.spec.general]") shall contain a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [dcl.type.general]") that is not a [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")[.](#17.sentence-1)
|
||||
|
||||
The[*member-declarator-list*](#nt:member-declarator-list "11.4.1 General [class.mem.general]") can be omitted only after a[*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]") or an [*enum-specifier*](dcl.enum#nt:enum-specifier "9.8.1 Enumeration declarations [dcl.enum]") or in a[friend declaration](class.friend "11.8.4 Friends [class.friend]")[.](#17.sentence-2)
|
||||
|
||||
A[*pure-specifier*](#nt:pure-specifier "11.4.1 General [class.mem.general]") shall be used only in the declaration of a[virtual function](class.virtual "11.7.3 Virtual 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.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*member-declaration*](#nt:member-declaration "11.4.1 General [class.mem.general]") appertains to each of the entities declared by the [*member-declarator*](#nt:member-declarator "11.4.1 General [class.mem.general]")*s*;
|
||||
it shall not appear if the optional [*member-declarator-list*](#nt:member-declarator-list "11.4.1 General [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.1 General [class.mem.general]") shall contain at most one of each[*virt-specifier*](#nt:virt-specifier "11.4.1 General [class.mem.general]")[.](#19.sentence-1)
|
||||
|
||||
A [*virt-specifier-seq*](#nt:virt-specifier-seq "11.4.1 General [class.mem.general]") shall appear only in the first declaration of a virtual member
|
||||
function ([[class.virtual]](class.virtual "11.7.3 Virtual 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.1 General")),
|
||||
an abstract class type ([[class.abstract]](class.abstract "11.7.4 Abstract 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.5 Names") 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.2 Object model"))
|
||||
are allocated so that later
|
||||
members have higher addresses within a class object ([[expr.rel]](expr.rel "7.6.9 Relational 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.3 Virtual functions")) and
|
||||
virtual base classes ([[class.mi]](class.mi "11.7.2 Multiple 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.5 Constructors"))[.](#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.5 Constructors [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.1 General [class.mem.general]") of two standard-layout struct ([[class.prop]](class.prop "11.2 Properties 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.9 Types")),
|
||||
|
||||
- [(27.2)](#27.2)
|
||||
|
||||
corresponding entities have the same alignment requirements ([[basic.align]](basic.align "6.8.3 Alignment")),
|
||||
|
||||
- [(27.3)](#27.3)
|
||||
|
||||
if a [*has-attribute-expression*](cpp.cond#nt:has-attribute-expression "15.2 Conditional inclusion [cpp.cond]") ([[cpp.cond]](cpp.cond "15.2 Conditional 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.11 No 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.2 Properties of classes")) types are[*layout-compatible classes*](#def:layout-compatible,class "11.4.1 General [class.mem.general]") if
|
||||
their common initial sequence comprises all members and bit-fields of
|
||||
both classes ([[basic.types]](basic.types "6.9 Types"))[.](#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.1 General"))[.](#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.5 Unions [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.2 The 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.4 Compound types"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static 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.1 General [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.11 Identifiers [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.1 Attribute syntax and semantics [dcl.attr.grammar]") ([[dcl.align]](dcl.align "9.13.2 Alignment 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.1 Attribute syntax and semantics [dcl.attr.grammar]"),
|
||||
|
||||
- [(32.9)](#32.9)
|
||||
|
||||
it is a bit-field ([[class.bit]](class.bit "11.4.10 Bit-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.11 No 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.2 Fundamental types"))
|
||||
returned by std::meta::data_member_spec ([[meta.reflection.define.aggregate]](meta.reflection.define.aggregate "21.4.16 Reflection class definition generation")) and
|
||||
can be reified as data members of a class using std::meta::define_aggregate[.](#32.sentence-4)
|
||||
|
||||
â *end note*]
|
||||
213
cppdraft/class/member/lookup.md
Normal file
213
cppdraft/class/member/lookup.md
Normal 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.2 Member 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.3 Conversion 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.2 Member 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.10 The 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.1 Preamble [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.2 Dependent 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.1 General [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.4 Class 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.3 Conversion 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.1 General"))[.](#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.4 Overload 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(); };
|
||||
|
||||

|
||||
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.13 Pointer-to-member conversions"), [[expr.ref]](expr.ref "7.6.1.5 Class member access"), [[class.access.base]](class.access.base "11.8.3 Accessibility 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
64
cppdraft/class/mfct.md
Normal 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.6 Function definitions")) in its class definition,
|
||||
it is inline ([[dcl.inline]](dcl.inline "9.2.8 The 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.6 Functions") and [[temp.arg]](temp.arg "13.4 Template 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*]
|
||||
41
cppdraft/class/mfct/non/static.md
Normal file
41
cppdraft/class/mfct/non/static.md
Normal 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.7 Derived classes"))
|
||||
from its class type, using the class member
|
||||
access syntax ([[expr.ref]](expr.ref "7.6.1.5 Class member access"), [[over.match.call]](over.match.call "12.2.2.2 Function 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.3 Function call"), [[over.match.call]](over.match.call "12.2.2.2 Function 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.1 General [dcl.decl.general]")*s*, which affect the type of the this pointer ([[expr.prim.this]](expr.prim.this "7.5.3 This")),
|
||||
and/or a [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]") ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"));
|
||||
both affect overload resolution ([[over.match.funcs]](over.match.funcs "12.2.2 Candidate 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.3 Virtual functions")) or pure virtual ([[class.abstract]](class.abstract "11.7.4 Abstract classes"))[.](#3.sentence-1)
|
||||
150
cppdraft/class/mi.md
Normal file
150
cppdraft/class/mi.md
Normal 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.3 Initializing bases and members")),
|
||||
cleanup ([[class.dtor]](class.dtor "11.4.7 Destructors")), and storage
|
||||
layout ([[class.mem]](class.mem "11.4 Class members"), [[class.access.spec]](class.access.spec "11.8.2 Access 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.2 Multiple 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.2 Multiple 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.2 Object 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)
|
||||
|
||||

|
||||
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.2 Member 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 { /* ... */ };
|
||||
|
||||

|
||||
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)
|
||||
|
||||

|
||||
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
108
cppdraft/class/name.md
Normal 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 "12 Overloading")) 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.5 Elaborated 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.6 Elaborated 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.5 Elaborated type specifiers [dcl.type.elab]") can also be used to declare
|
||||
an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") as a [*class-name*](class.pre#nt:class-name "11.1 Preamble [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.4 Friends"),
|
||||
operator functions in [[over.oper]](over.oper "12.4 Overloaded 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.5 Elaborated type specifiers [dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers")) can also
|
||||
be used as a [*type-specifier*](dcl.type.general#nt:type-specifier "9.2.9.1 General [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.11 Identifiers [lex.name]") is seen in the class definition or[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated 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.3 Names of template specializations [temp.names]") is only a [*class-name*](class.pre#nt:class-name "11.1 Preamble [class.pre]") if its [*template-name*](temp.names#nt:template-name "13.3 Names of template specializations [temp.names]") names a class template[.](#5.sentence-1)
|
||||
56
cppdraft/class/nest.md
Normal file
56
cppdraft/class/nest.md
Normal 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.12 Nested class declarations [class.nest]")[.](#1.sentence-2)
|
||||
|
||||
[*Note [1](#note-1)*:
|
||||
|
||||
See [[expr.prim.id]](expr.prim.id "7.5.5 Names") 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.4 Friends")) 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
21
cppdraft/class/paths.md
Normal 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
163
cppdraft/class/pre.md
Normal 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.1 Preamble [class.pre]") ([[class.name]](class.name "11.3 Class names")) within its
|
||||
scope[.](#1.sentence-2)
|
||||
|
||||
[class-name:](#nt:class-name "11.1 Preamble [class.pre]")
|
||||
[*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]")
|
||||
[*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]")
|
||||
|
||||
A [*class-specifier*](#nt:class-specifier "11.1 Preamble [class.pre]") or
|
||||
an [*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]") ([[dcl.type.elab]](dcl.type.elab "9.2.9.5 Elaborated type specifiers")) is used to
|
||||
make a [*class-name*](#nt:class-name "11.1 Preamble [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.1 Preamble [class.pre]")
|
||||
[*class-head*](#nt:class-head "11.1 Preamble [class.pre]") { [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [class.mem.general]")opt }
|
||||
|
||||
[class-head:](#nt:class-head "11.1 Preamble [class.pre]")
|
||||
[*class-key*](#nt:class-key "11.1 Preamble [class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*class-head-name*](#nt:class-head-name "11.1 Preamble [class.pre]") [*class-property-specifier-seq*](#nt:class-property-specifier-seq "11.1 Preamble [class.pre]")opt [*base-clause*](class.derived.general#nt:base-clause "11.7.1 General [class.derived.general]")opt
|
||||
[*class-key*](#nt:class-key "11.1 Preamble [class.pre]") [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]")opt [*base-clause*](class.derived.general#nt:base-clause "11.7.1 General [class.derived.general]")opt
|
||||
|
||||
[class-head-name:](#nt:class-head-name "11.1 Preamble [class.pre]")
|
||||
[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]")opt [*class-name*](#nt:class-name "11.1 Preamble [class.pre]")
|
||||
|
||||
[class-property-specifier-seq:](#nt:class-property-specifier-seq "11.1 Preamble [class.pre]")
|
||||
[*class-property-specifier*](#nt:class-property-specifier "11.1 Preamble [class.pre]") [*class-property-specifier-seq*](#nt:class-property-specifier-seq "11.1 Preamble [class.pre]")opt
|
||||
|
||||
[class-property-specifier:](#nt:class-property-specifier "11.1 Preamble [class.pre]")
|
||||
final
|
||||
trivially_relocatable_if_eligible
|
||||
replaceable_if_eligible
|
||||
|
||||
[class-key:](#nt:class-key "11.1 Preamble [class.pre]")
|
||||
class
|
||||
struct
|
||||
union
|
||||
|
||||
A class declaration where the [*class-name*](#nt:class-name "11.1 Preamble [class.pre]") in the [*class-head-name*](#nt:class-head-name "11.1 Preamble [class.pre]") is a [*simple-template-id*](temp.names#nt:simple-template-id "13.3 Names of template specializations [temp.names]") shall be an explicit specialization ([[temp.expl.spec]](temp.expl.spec "13.9.4 Explicit specialization")) or
|
||||
a partial specialization ([[temp.spec.partial]](temp.spec.partial "13.7.6 Partial specialization"))[.](#1.sentence-5)
|
||||
|
||||
A [*class-specifier*](#nt:class-specifier "11.1 Preamble [class.pre]") whose[*class-head*](#nt:class-head "11.1 Preamble [class.pre]") omits the[*class-head-name*](#nt:class-head-name "11.1 Preamble [class.pre]") defines an [*unnamed class*](#def:class,unnamed "11.1 Preamble [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.1 Preamble [class.pre]") is an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]");
|
||||
it is not looked up, and the [*class-specifier*](#nt:class-specifier "11.1 Preamble [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.1 Preamble [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.1 Preamble [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.1 Preamble [class.pre]") is commonly referred to as a [*class
|
||||
definition*](#def:definition,class "11.1 Preamble [class.pre]")[.](#2.sentence-3)
|
||||
|
||||
A class is considered defined after the closing brace of its[*class-specifier*](#nt:class-specifier "11.1 Preamble [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.1 Attribute 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.1 Attribute 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.1 Preamble [class.pre]") contains a [*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified names [expr.prim.id.qual]"),
|
||||
the [*class-specifier*](#nt:class-specifier "11.1 Preamble [class.pre]") shall not inhabit a class scope[.](#3.sentence-1)
|
||||
|
||||
If its [*class-name*](#nt:class-name "11.1 Preamble [class.pre]") is an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]"),
|
||||
the [*class-specifier*](#nt:class-specifier "11.1 Preamble [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.3 Qualified 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.1 Preamble [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.1 Preamble [class.pre]") determines
|
||||
whether the class is a union ([[class.union]](class.union "11.5 Unions")) and
|
||||
whether access is public or private by default ([[class.access]](class.access "11.8 Member 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.1 Preamble [class.pre]") shall appear at most once
|
||||
within a single [*class-property-specifier-seq*](#nt:class-property-specifier-seq "11.1 Preamble [class.pre]")[.](#5.sentence-1)
|
||||
|
||||
Whenever a [*class-key*](#nt:class-key "11.1 Preamble [class.pre]") is followed
|
||||
by a [*class-head-name*](#nt:class-head-name "11.1 Preamble [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.1 Preamble [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.1 Preamble [class.pre]")final and that class appears as a [*class-or-decltype*](class.derived.general#nt:class-or-decltype "11.7.1 General [class.derived.general]") in a [*base-clause*](class.derived.general#nt:base-clause "11.7.1 General [class.derived.general]") ([[class.derived]](class.derived "11.7 Derived 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.11 No 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.2 Simple assignment"), [[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator")),
|
||||
passed as arguments to functions ([[dcl.init]](dcl.init "9.5 Initializers"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/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.3 Deleted definitions") and [[class.access]](class.access "11.8 Member access control"))[.](#8.sentence-1)
|
||||
|
||||
Other plausible operators, such as equality comparison,
|
||||
can be defined by the user; see [[over.oper]](over.oper "12.4 Overloaded operators")[.](#8.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
315
cppdraft/class/prop.md
Normal file
315
cppdraft/class/prop.md
Normal 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.2 Properties 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.4 Special member functions"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors"), [[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator")),
|
||||
|
||||
- [(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.7 Destructors"))[.](#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.2 Properties 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.2 Properties 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.2 Properties 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.1 Preamble [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.2 Properties 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.1 General")),
|
||||
|
||||
- [(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.19 Assignment and compound assignment operators"), [[over.assign]](over.assign "12.4.3.2 Simple 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.2 Properties 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.1 Preamble [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.2 Properties 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.3 Virtual functions [class.virtual]") and no[virtual base classes](class.mi "11.7.2 Multiple base classes [class.mi]"),
|
||||
|
||||
- [(10.3)](#10.3)
|
||||
|
||||
has the same [access control](class.access "11.8 Member 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.2 Properties of classes [class.prop]") is a standard-layout class
|
||||
defined with the [*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") struct or the[*class-key*](class.pre#nt:class-key "11.1 Preamble [class.pre]") class[.](#12.sentence-1)
|
||||
|
||||
A [*standard-layout union*](#def:union,standard-layout "11.2 Properties of classes [class.prop]") is a standard-layout class
|
||||
defined with the[*class-key*](class.pre#nt:class-key "11.1 Preamble [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.1 General") and [[expr.rel]](expr.rel "7.6.9 Relational 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.2 Aggregates")[.](#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.2 Properties 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.10 Equality operators"))[.](#footnote-88.sentence-1)
|
||||
39
cppdraft/class/protected.md
Normal file
39
cppdraft/class/protected.md
Normal 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.8 Member 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.3 Accessibility 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.2 Unary operators")), the[*nested-name-specifier*](expr.prim.id.qual#nt:nested-name-specifier "7.5.5.3 Qualified 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.5 Class 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
40
cppdraft/class/qual.md
Normal 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.1 Preamble")), or
|
||||
|
||||
- [(1.2)](#1.2)
|
||||
|
||||
if N is dependent and
|
||||
is the terminal name of a [*using-declarator*](namespace.udecl#nt:using-declarator "9.10 The using declaration [namespace.udecl]") ([[namespace.udecl]](namespace.udecl "9.10 The 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.1 General [dcl.decl.general]") of a (friend) declaration of a constructor or
|
||||
in a [*using-declaration*](namespace.udecl#nt:using-declaration "9.10 The 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.3 Qualified names [expr.prim.id.qual]"), an[*elaborated-type-specifier*](dcl.type.elab#nt:elaborated-type-specifier "9.2.9.5 Elaborated type specifiers [dcl.type.elab]"), or a [*base-specifier*](class.derived.general#nt:base-specifier "11.7.1 General [class.derived.general]")[.](#footnote-18.sentence-1)
|
||||
105
cppdraft/class/slice.md
Normal file
105
cppdraft/class/slice.md
Normal 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();
|
||||
41
cppdraft/class/slice/overview.md
Normal file
41
cppdraft/class/slice/overview.md
Normal 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
115
cppdraft/class/spaceship.md
Normal 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.3 Three-way comparison [class.spaceship]") of type R ([[cmp.categories]](cmp.categories "17.12.2 Comparison 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.1 Defaulted 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.1 Preamble")) 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.3 Three-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.2 Class 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.3 Class weak_ordering"))[.](#4.2.sentence-1)
|
||||
|
||||
- [(4.3)](#4.3)
|
||||
|
||||
Otherwise, U is std::strong_ordering ([[cmp.strongord]](cmp.strongord "17.12.2.4 Class 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
182
cppdraft/class/static.md
Normal 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.3 Qualified 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.5 Class 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.8 Member 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.1 General [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.2 Member 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.3 This"))[.](#mfct-2.sentence-1)
|
||||
|
||||
A static member function cannot be qualified with const,volatile, or virtual ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#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.2 Storage class specifiers"))[.](#data-2.sentence-1)
|
||||
|
||||
A static data member shall not be a direct member ([[class.mem]](class.mem "11.4 Class members"))
|
||||
of an unnamed ([[class.pre]](class.pre "11.1 Preamble")) or local ([[class.local]](class.local "11.6 Local class declarations")) class or
|
||||
of a (possibly indirectly) nested class ([[class.nest]](class.nest "11.4.12 Nested 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.1 General [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.7 Class 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.1 General [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.2 Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"), and [[basic.start.term]](basic.start.term "6.10.3.4 Termination")[.](#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.1 General [dcl.init.general]") in which every[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") that is an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") is a constant expression ([[expr.const]](expr.const "7.7 Constant 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.3 One-definition rule")) in the program and the
|
||||
namespace scope definition shall not contain an [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.1 General [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.7 Redeclaration 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.1 General [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.3 One-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.7 Program and linkage"))[.](#data-6.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
120
cppdraft/class/static/data.md
Normal file
120
cppdraft/class/static/data.md
Normal 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.2 Storage class specifiers"))[.](#2.sentence-1)
|
||||
|
||||
A static data member shall not be a direct member ([[class.mem]](class.mem "11.4 Class members"))
|
||||
of an unnamed ([[class.pre]](class.pre "11.1 Preamble")) or local ([[class.local]](class.local "11.6 Local class declarations")) class or
|
||||
of a (possibly indirectly) nested class ([[class.nest]](class.nest "11.4.12 Nested 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.1 General [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.7 Class 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.1 General [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.2 Static initialization"), [[basic.start.dynamic]](basic.start.dynamic "6.10.3.3 Dynamic initialization of non-block variables"), and [[basic.start.term]](basic.start.term "6.10.3.4 Termination")[.](#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.1 General [dcl.init.general]") in which every[*initializer-clause*](dcl.init.general#nt:initializer-clause "9.5.1 General [dcl.init.general]") that is an [*assignment-expression*](expr.assign#nt:assignment-expression "7.6.19 Assignment and compound assignment operators [expr.assign]") is a constant expression ([[expr.const]](expr.const "7.7 Constant 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.3 One-definition rule")) in the program and the
|
||||
namespace scope definition shall not contain an [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.1 General [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.7 Redeclaration 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.1 General [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.3 One-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.7 Program and linkage"))[.](#6.sentence-1)
|
||||
|
||||
â *end note*]
|
||||
44
cppdraft/class/static/general.md
Normal file
44
cppdraft/class/static/general.md
Normal 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.3 Qualified 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.5 Class 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.8 Member 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.1 General [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*]
|
||||
32
cppdraft/class/static/mfct.md
Normal file
32
cppdraft/class/static/mfct.md
Normal 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.2 Member 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.3 This"))[.](#2.sentence-1)
|
||||
|
||||
A static member function cannot be qualified with const,volatile, or virtual ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#2.sentence-2)
|
||||
|
||||
â *end note*]
|
||||
423
cppdraft/class/temporary.md
Normal file
423
cppdraft/class/temporary.md
Normal 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.7 Temporary 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.5 Temporary 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.3 Context 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.8 Member 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.6 Decltype specifiers [dcl.type.decltype]") ([[dcl.type.decltype]](dcl.type.decltype "9.2.9.6 Decltype 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.4 References"), [[expr.type.conv]](expr.type.conv "7.6.1.4 Explicit type conversion (functional notation)"), [[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast"), [[expr.const.cast]](expr.const.cast "7.6.1.11 Const cast"), [[expr.cast]](expr.cast "7.6.3 Explicit type conversion (cast notation)")),
|
||||
|
||||
- [(2.2)](#2.2)
|
||||
|
||||
when performing certain member accesses on a class prvalue ([[expr.ref]](expr.ref "7.6.1.5 Class member access"), [[expr.mptr.oper]](expr.mptr.oper "7.6.4 Pointer-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.3 Function call")),
|
||||
|
||||
- [(2.4)](#2.4)
|
||||
|
||||
when performing an array-to-pointer conversion or subscripting on an array prvalue ([[conv.array]](conv.array "7.3.3 Array-to-pointer conversion"), [[expr.sub]](expr.sub "7.6.1.2 Subscripting")),
|
||||
|
||||
- [(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.1 General [dcl.init.general]") ([[dcl.init.list]](dcl.init.list "9.5.5 List-initialization")),
|
||||
|
||||
- [(2.6)](#2.6)
|
||||
|
||||
for certain unevaluated operands ([[expr.typeid]](expr.typeid "7.6.1.8 Type identification"), [[expr.sizeof]](expr.sizeof "7.6.2.5 Sizeof")), 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.3 Context 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.4 Special 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.1 Sequential 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.5 Initializers"))[.](#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.3 Captures"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/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.5 Temporary materialization conversion")),
|
||||
|
||||
- [(6.2)](#6.2)
|
||||
|
||||
( [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") ),
|
||||
where [*expression*](expr.comma#nt:expression "7.6.20 Comma operator [expr.comma]") is one of these expressions,
|
||||
|
||||
- [(6.3)](#6.3)
|
||||
|
||||
subscripting ([[expr.sub]](expr.sub "7.6.1.2 Subscripting")) 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.5 Class 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.4 Pointer-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.11 Const cast")),
|
||||
|
||||
* [(6.6.2)](#6.6.2)
|
||||
|
||||
static_cast ([[expr.static.cast]](expr.static.cast "7.6.1.9 Static cast")),
|
||||
|
||||
* [(6.6.3)](#6.6.3)
|
||||
|
||||
dynamic_cast ([[expr.dynamic.cast]](expr.dynamic.cast "7.6.1.7 Dynamic cast")), or
|
||||
|
||||
* [(6.6.4)](#6.6.4)
|
||||
|
||||
reinterpret_cast ([[expr.reinterpret.cast]](expr.reinterpret.cast "7.6.1.10 Reinterpret 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.16 Conditional 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.20 Comma 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.4 Explicit type conversion (functional notation)"), [[expr.cast]](expr.cast "7.6.3 Explicit 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.3 Function 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.1 General [expr.post.general]") ([[dcl.init]](dcl.init "9.5 Initializers"))
|
||||
persists until the completion of the full-expression
|
||||
containing the [*expression-list*](expr.post.general#nt:expression-list "7.6.1.1 General [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.8 New [expr.new]") ([[expr.new]](expr.new "7.6.2.8 New")) persists until the completion of the full-expression containing the [*new-initializer*](expr.new#nt:new-initializer "7.6.2.8 New [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.1 Preamble [stmt.pre]") of
|
||||
either a range-based for statement
|
||||
or an enumerating expansion statement ([[stmt.expand]](stmt.expand "8.7 Expansion 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.1 Preamble [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.1 Preamble [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.7 Expansion 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.7 Expansion statements [stmt.expand]"),
|
||||
the object persists for the lifetime of the reference
|
||||
initialized by the [*expansion-initializer*](stmt.expand#nt:expansion-initializer "8.7 Expansion 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.7 Structured binding declarations"))[.](#9.sentence-1)
|
||||
|
||||
Any temporary objects introduced by
|
||||
the [*initializer*](dcl.init.general#nt:initializer "9.5.1 General [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.2 Static storage duration"), [[basic.stc.thread]](basic.stc.thread "6.8.6.3 Thread storage duration"), [[basic.stc.auto]](basic.stc.auto "6.8.6.4 Automatic 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.5 List-initialization")) with its
|
||||
underlying temporary array[.](#footnote-25.sentence-1)
|
||||
265
cppdraft/class/union.md
Normal file
265
cppdraft/class/union.md
Normal 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.1 General [class.union.general]") is a class defined with the [*class-key*](class.pre#nt:class-key "11.1 Preamble [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.1 General [class.union.general]") if its name refers to an object
|
||||
whose lifetime has begun and has not ended ([[basic.life]](basic.life "6.8.4 Lifetime"))[.](#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.4 Class 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.4 Class 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.4 Compound types"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static 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.3 Virtual 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.3 Copy/move constructors")),
|
||||
copy assignment operator, or
|
||||
move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/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.3 Deleted 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.4 String 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.5 Class 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.19 Assignment and compound assignment operators"))
|
||||
or a trivial assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator")),
|
||||
for each element X of S(E1) and
|
||||
each anonymous union member X ([[class.union.anon]](#anon "11.5.2 Anonymous 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.4 Lifetime"),
|
||||
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.4 Lifetime"))[.](#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.4 Lifetime"))}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.4 Class 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.8 New [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.8 New [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.1 General [class.mem.general]") } ;
|
||||
|
||||
is called an [*anonymous union*](#def:anonymous_union "11.5.2 Anonymous 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.2 Anonymous unions [class.union.anon]") if it is a non-static data member or
|
||||
an [*anonymous union variable*](#def:variable,anonymous_union "11.5.2 Anonymous unions [class.union.anon]") otherwise[.](#anon-1.sentence-1)
|
||||
|
||||
Each [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") in the [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [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.1 Preamble [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.2 Storage 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.2 Storage 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.2 Storage 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.2 Aggregates")[.](#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.2 Anonymous 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.2 Anonymous 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*]
|
||||
95
cppdraft/class/union/anon.md
Normal file
95
cppdraft/class/union/anon.md
Normal 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.1 General [class.mem.general]") } ;
|
||||
|
||||
is called an [*anonymous union*](#def:anonymous_union "11.5.2 Anonymous 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.2 Anonymous unions [class.union.anon]") if it is a non-static data member or
|
||||
an [*anonymous union variable*](#def:variable,anonymous_union "11.5.2 Anonymous unions [class.union.anon]") otherwise[.](#1.sentence-1)
|
||||
|
||||
Each [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") in the [*member-specification*](class.mem.general#nt:member-specification "11.4.1 General [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.1 Preamble [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.2 Storage 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.2 Storage 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.2 Storage 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.2 Aggregates")[.](#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.2 Anonymous 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.2 Anonymous 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*]
|
||||
175
cppdraft/class/union/general.md
Normal file
175
cppdraft/class/union/general.md
Normal 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.1 General [class.union.general]") is a class defined with the [*class-key*](class.pre#nt:class-key "11.1 Preamble [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.1 General [class.union.general]") if its name refers to an object
|
||||
whose lifetime has begun and has not ended ([[basic.life]](basic.life "6.8.4 Lifetime"))[.](#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.4 Class 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.4 Class 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.4 Compound types"), [[expr.static.cast]](expr.static.cast "7.6.1.9 Static 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.3 Virtual 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.3 Copy/move constructors")),
|
||||
copy assignment operator, or
|
||||
move assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/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.3 Deleted 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.4 String 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.5 Class 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.19 Assignment and compound assignment operators"))
|
||||
or a trivial assignment operator ([[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator")),
|
||||
for each element X of S(E1) and
|
||||
each anonymous union member X ([[class.union.anon]](class.union.anon "11.5.2 Anonymous 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.4 Lifetime"),
|
||||
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.4 Lifetime"))[.](#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.4 Lifetime"))}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.4 Class 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.8 New [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.8 New [expr.new]") as follows:u.m.~M();new (&u.n) N;
|
||||
|
||||
â *end example*]
|
||||
332
cppdraft/class/virtual.md
Normal file
332
cppdraft/class/virtual.md
Normal 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.3 Virtual 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.3 Virtual 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.1 General")) to a declaration of F,
|
||||
ignoring trailing [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [temp.pre]")*s*,
|
||||
then G [*overrides*](#def:function,virtual,override "11.7.3 Virtual 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.3 Virtual functions [class.virtual]") unless the most derived class ([[intro.object]](intro.object "6.8.2 Object 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.1 General [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.1 General [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.1 Preamble [temp.pre]") ([[dcl.decl]](dcl.decl "9.3 Declarators"))[.](#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.3 Constrained 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.1 General [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.3 Virtual 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.2 Point 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.3 Function 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.3 Function 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.3 Function 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.4 Friends")) 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.4 Abstract classes")) in that class, or both; no diagnostic is
|
||||
required ([[basic.def.odr]](basic.def.odr "6.3 One-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.3 Qualified 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.6 Function 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 "12 Overloading"))
|
||||
as a virtual function is not necessarily virtual and
|
||||
does not override[.](#footnote-94.sentence-1)
|
||||
|
||||
Access control ([[class.access]](class.access "11.8 Member 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)
|
||||
Reference in New Issue
Block a user