2817 lines
139 KiB
Markdown
2817 lines
139 KiB
Markdown
[class.mem]
|
||
|
||
# 11 Classes [[class]](./#class)
|
||
|
||
## 11.4 Class members [class.mem]
|
||
|
||
### [11.4.1](#general) General [[class.mem.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](#general-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]")[.](#general-1.sentence-1)
|
||
|
||
[*Note [1](#general-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")[.](#general-1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[2](#general-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[.](#general-2.sentence-1)
|
||
|
||
[3](#general-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[.](#general-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[.](#general-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[.](#general-3.sentence-3)
|
||
|
||
[*Note [2](#general-note-2)*:
|
||
|
||
A specialization of a static data member template is a static data member[.](#general-3.sentence-4)
|
||
|
||
A specialization of a member function template is a member function[.](#general-3.sentence-5)
|
||
|
||
A specialization of a member class template is a nested class[.](#general-3.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
[4](#general-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)](#general-4.1)
|
||
|
||
a friend declaration ([[class.friend]](class.friend "11.8.4 Friends")),
|
||
|
||
- [(4.2)](#general-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)](#general-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)](#general-4.4)
|
||
|
||
a [*static_assert-declaration*](dcl.pre#nt:static_assert-declaration "9.1 Preamble [dcl.pre]"),
|
||
|
||
- [(4.5)](#general-4.5)
|
||
|
||
a [*consteval-block-declaration*](dcl.pre#nt:consteval-block-declaration "9.1 Preamble [dcl.pre]"),
|
||
|
||
- [(4.6)](#general-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)](#general-4.7)
|
||
|
||
an [*empty-declaration*](dcl.pre#nt:empty-declaration "9.1 Preamble [dcl.pre]")[.](#general-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](#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[.](#general-4.sentence-2)
|
||
|
||
[5](#general-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]")[.](#general-5.sentence-1)
|
||
|
||
A [*member function*](#def:member_function "11.4.1 General [class.mem.general]") is a member that is a function[.](#general-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]")[.](#general-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[.](#general-5.sentence-4)
|
||
|
||
[6](#general-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[.](#general-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)[.](#general-6.sentence-2)
|
||
|
||
[7](#general-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[.](#general-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â[.](#general-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[.](#general-7.sentence-3)
|
||
|
||
The size and alignment of C are the same as
|
||
the size and alignment of D[.](#general-7.sentence-4)
|
||
|
||
[8](#general-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)](#general-8.1)
|
||
|
||
a nested class or member
|
||
class template can be declared and then later defined, and
|
||
|
||
- [(8.2)](#general-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]")[.](#general-8.sentence-1)
|
||
|
||
[*Note [3](#general-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"))[.](#general-8.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[9](#general-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"))[.](#general-9.sentence-1)
|
||
|
||
The member shall not be a non-static data member[.](#general-9.sentence-2)
|
||
|
||
[10](#general-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)](#general-10.1)
|
||
|
||
function body ([[dcl.fct.def.general]](dcl.fct.def.general "9.6.1 General")),
|
||
|
||
- [(10.2)](#general-10.2)
|
||
|
||
default argument ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default arguments")),
|
||
|
||
- [(10.3)](#general-10.3)
|
||
|
||
default template argument ([[temp.param]](temp.param "13.2 Template parameters")),
|
||
|
||
- [(10.4)](#general-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)](#general-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)](#general-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[.](#general-10.sentence-1)
|
||
|
||
[*Note [4](#general-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[.](#general-10.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[11](#general-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[.](#general-11.sentence-1)
|
||
|
||
Otherwise, C is incomplete at P[.](#general-11.sentence-2)
|
||
|
||
[12](#general-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]")[.](#general-12.sentence-1)
|
||
|
||
[13](#general-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]")[.](#general-13.sentence-1)
|
||
|
||
[*Example [1](#general-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](#general-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]")[.](#general-14.sentence-1)
|
||
|
||
[*Example [2](#general-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](#general-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[.](#general-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"))[.](#general-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[.](#general-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[.](#general-15.sentence-4)
|
||
|
||
[16](#general-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]")[.](#general-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[.](#general-16.sentence-2)
|
||
|
||
[17](#general-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]")[.](#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]")[.](#general-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[.](#general-17.sentence-3)
|
||
|
||
[18](#general-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[.](#general-18.sentence-1)
|
||
|
||
[19](#general-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]")[.](#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"))[.](#general-19.sentence-2)
|
||
|
||
[20](#general-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[.](#general-20.sentence-1)
|
||
|
||
[*Note [5](#general-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[.](#general-20.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[21](#general-21)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L854)
|
||
|
||
[*Note [6](#general-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[.](#general-21.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[22](#general-22)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L860)
|
||
|
||
[*Note [7](#general-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[.](#general-22.sentence-1)
|
||
|
||
There are no special member function types or data member types[.](#general-22.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[23](#general-23)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L867)
|
||
|
||
[*Example [3](#general-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[.](#general-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[.](#general-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[.](#general-23.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
[24](#general-24)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L892)
|
||
|
||
[*Note [8](#general-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"))[.](#general-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"))[.](#general-24.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[25](#general-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)](#general-25.1)
|
||
|
||
every static data member of class T;
|
||
|
||
- [(25.2)](#general-25.2)
|
||
|
||
every member function of class T;
|
||
[*Note [9](#general-note-9)*:
|
||
This restriction does not apply to constructors, which do not have
|
||
names ([[class.ctor]](#class.ctor "11.4.5 Constructors"))[.](#general-25.2.sentence-1)
|
||
â *end note*]
|
||
|
||
- [(25.3)](#general-25.3)
|
||
|
||
every member of class T that is itself a type;
|
||
|
||
- [(25.4)](#general-25.4)
|
||
|
||
every member template of class T;
|
||
|
||
- [(25.5)](#general-25.5)
|
||
|
||
every enumerator of every member of class T that is an
|
||
unscoped enumeration type; and
|
||
|
||
- [(25.6)](#general-25.6)
|
||
|
||
every member of every anonymous union that is a member of classT[.](#general-25.sentence-1)
|
||
|
||
[26](#general-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[.](#general-26.sentence-1)
|
||
|
||
[27](#general-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)](#general-27.1)
|
||
|
||
corresponding entities
|
||
have layout-compatible types ([[basic.types]](basic.types "6.9 Types")),
|
||
|
||
- [(27.2)](#general-27.2)
|
||
|
||
corresponding entities have the same alignment requirements ([[basic.align]](basic.align "6.8.3 Alignment")),
|
||
|
||
- [(27.3)](#general-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)](#general-27.4)
|
||
|
||
either both entities are bit-fields with the same width
|
||
or neither is a bit-field[.](#general-27.sentence-1)
|
||
|
||
[*Example [4](#general-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[.](#general-27.sentence-2)
|
||
|
||
The common initial sequence of A and C and
|
||
of A and D comprises the first member in each case[.](#general-27.sentence-3)
|
||
|
||
The common initial sequence of A and E is empty[.](#general-27.sentence-4)
|
||
|
||
â *end example*]
|
||
|
||
[28](#general-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"))[.](#general-28.sentence-1)
|
||
|
||
[29](#general-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"))[.](#general-29.sentence-1)
|
||
|
||
[30](#general-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[.](#general-30.sentence-1)
|
||
|
||
[*Example [5](#general-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](#general-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"))[.](#general-30.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[31](#general-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[.](#general-31.sentence-1)
|
||
|
||
Its
|
||
address is also the same as the address of each of its base class subobjects[.](#general-31.sentence-2)
|
||
|
||
[*Note [11](#general-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[.](#general-31.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [12](#general-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"))[.](#general-31.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[32](#general-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)](#general-32.1)
|
||
|
||
T is a type,
|
||
|
||
- [(32.2)](#general-32.2)
|
||
|
||
N is an [*identifier*](lex.name#nt:identifier "5.11 Identifiers [lex.name]") or â¥,
|
||
|
||
- [(32.3)](#general-32.3)
|
||
|
||
A is an alignment or â¥,
|
||
|
||
- [(32.4)](#general-32.4)
|
||
|
||
W is a bit-field width or â¥, and
|
||
|
||
- [(32.5)](#general-32.5)
|
||
|
||
NUA is a boolean value[.](#general-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 â¥[.](#general-32.sentence-2)
|
||
|
||
[*Note [13](#general-note-13)*:
|
||
|
||
The components of a data member description describe a data member such that
|
||
|
||
- [(32.6)](#general-32.6)
|
||
|
||
its type is specified using the type given by T,
|
||
|
||
- [(32.7)](#general-32.7)
|
||
|
||
it is declared with the name given by N if N is not ⥠and is otherwise unnamed,
|
||
|
||
- [(32.8)](#general-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)](#general-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)](#general-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[.](#general-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[.](#general-32.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
### [11.4.2](#class.mfct) Member functions [[class.mfct]](class.mfct)
|
||
|
||
[1](#class.mfct-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"))[.](#class.mfct-1.sentence-1)
|
||
|
||
[*Note [1](#class.mfct-note-1)*:
|
||
|
||
A member function is also inline if it is declaredinline, constexpr, or consteval[.](#class.mfct-1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[2](#class.mfct-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1069)
|
||
|
||
[*Example [1](#class.mfct-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[.](#class.mfct-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[.](#class.mfct-2.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[3](#class.mfct-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[.](#class.mfct-3.sentence-1)
|
||
|
||
[4](#class.mfct-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1095)
|
||
|
||
[*Note [2](#class.mfct-note-2)*:
|
||
|
||
A member function can be declared (but not defined) using a typedef for
|
||
a function type[.](#class.mfct-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")[.](#class.mfct-4.sentence-2)
|
||
|
||
[*Example [2](#class.mfct-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*]
|
||
|
||
### [11.4.3](#class.mfct.non.static) Non-static member functions [[class.mfct.non.static]](class.mfct.non.static)
|
||
|
||
[1](#class.mfct.non.static-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"))[.](#class.mfct.non.static-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[.](#class.mfct.non.static-1.sentence-2)
|
||
|
||
[2](#class.mfct.non.static-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1131)
|
||
|
||
[*Note [1](#class.mfct.non.static-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"))[.](#class.mfct.non.static-2.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[3](#class.mfct.non.static-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"))[.](#class.mfct.non.static-3.sentence-1)
|
||
|
||
### [11.4.4](#special) Special member functions [[special]](special)
|
||
|
||
[1](#special-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1154)
|
||
|
||
Default constructors ([[class.default.ctor]](#class.default.ctor "11.4.5.2 Default constructors")),
|
||
copy constructors, move constructors ([[class.copy.ctor]](#class.copy.ctor "11.4.5.3 Copy/move constructors")),
|
||
copy assignment operators, move assignment operators ([[class.copy.assign]](#class.copy.assign "11.4.6 Copy/move assignment operator")),
|
||
and prospective destructors ([[class.dtor]](#class.dtor "11.4.7 Destructors")) are[*special member functions*](#def:special_member_functions)[.](#special-1.sentence-1)
|
||
|
||
[*Note [1](#special-note-1)*:
|
||
|
||
The implementation will implicitly declare these member functions for some class
|
||
types when the program does not explicitly declare them[.](#special-1.sentence-2)
|
||
|
||
The implementation will implicitly define them
|
||
as needed ([[dcl.fct.def.default]](dcl.fct.def.default "9.6.2 Explicitly-defaulted functions"))[.](#special-1.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
An implicitly-declared special member function is declared at the closing} of the [*class-specifier*](class.pre#nt:class-specifier "11.1 Preamble [class.pre]")[.](#special-1.sentence-4)
|
||
|
||
Programs shall not define implicitly-declared special member functions[.](#special-1.sentence-5)
|
||
|
||
[2](#special-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1175)
|
||
|
||
Programs may explicitly refer to implicitly-declared special member functions[.](#special-2.sentence-1)
|
||
|
||
[*Example [1](#special-example-1)*:
|
||
|
||
A program may explicitly call or form a pointer to member
|
||
to an implicitly-declared special member function[.](#special-2.sentence-2)
|
||
|
||
struct A { }; // implicitly declared A::operator=struct B : A { B& operator=(const B &);};
|
||
B& B::operator=(const B& s) {this->A::operator=(s); // well-formedreturn *this;} â *end example*]
|
||
|
||
[3](#special-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1193)
|
||
|
||
[*Note [2](#special-note-2)*:
|
||
|
||
The special member functions affect the way objects of class type are created,
|
||
copied, moved, and destroyed, and how values can be converted to values of other types[.](#special-3.sentence-1)
|
||
|
||
Often such special member functions are called implicitly[.](#special-3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[4](#special-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1200)
|
||
|
||
Special member functions obey the usual access rules ([[class.access]](class.access "11.8 Member access control"))[.](#special-4.sentence-1)
|
||
|
||
[*Example [2](#special-example-2)*:
|
||
|
||
Declaring a constructor protected
|
||
ensures that only derived classes and friends can create objects using it[.](#special-4.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[5](#special-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1208)
|
||
|
||
Two special member functions are of the same kind if
|
||
|
||
- [(5.1)](#special-5.1)
|
||
|
||
they are both default constructors,
|
||
|
||
- [(5.2)](#special-5.2)
|
||
|
||
they are both copy or move constructors
|
||
with the same first parameter type, or
|
||
|
||
- [(5.3)](#special-5.3)
|
||
|
||
they are both copy or move assignment operators
|
||
with the same first parameter type
|
||
and the same [*cv-qualifier*](dcl.decl.general#nt:cv-qualifier "9.3.1 General [dcl.decl.general]")*s* and [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1 General [dcl.decl.general]"), if any[.](#special-5.sentence-1)
|
||
|
||
[6](#special-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1219)
|
||
|
||
An [*eligible special member function*](#def:special_member_function,eligible "11.4.4 Special member functions [special]") is a special member function for which:
|
||
|
||
- [(6.1)](#special-6.1)
|
||
|
||
the function is not deleted,
|
||
|
||
- [(6.2)](#special-6.2)
|
||
|
||
the associated constraints ([[temp.constr]](temp.constr "13.5 Template constraints")), if any, are satisfied, and
|
||
|
||
- [(6.3)](#special-6.3)
|
||
|
||
no special member function of the same kind
|
||
whose associated constraints, if any, are satisfied
|
||
is more constrained ([[temp.constr.order]](temp.constr.order "13.5.5 Partial ordering by constraints"))[.](#special-6.sentence-1)
|
||
|
||
[7](#special-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1229)
|
||
|
||
For a class, its non-static data members, its non-virtual direct base classes,
|
||
and, if the class is not abstract ([[class.abstract]](class.abstract "11.7.4 Abstract classes")), its virtual base
|
||
classes are called its [*potentially constructed subobjects*](#def:potentially_constructed_subobjects)[.](#special-7.sentence-1)
|
||
|
||
### [11.4.5](#class.ctor) Constructors [[class.ctor]](class.ctor)
|
||
|
||
#### [11.4.5.1](#class.ctor.general) General [[class.ctor.general]](class.ctor.general)
|
||
|
||
[1](#class.ctor.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)](#class.ctor.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)](#class.ctor.general-1.2)
|
||
|
||
otherwise, in a [*member-declaration*](#nt:member-declaration "11.4.1 General [class.mem.general]") that belongs to the[*member-specification*](#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)](#class.ctor.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[.](#class.ctor.general-1.sentence-1)
|
||
|
||
Constructors do not have names[.](#class.ctor.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]")[.](#class.ctor.general-1.sentence-3)
|
||
|
||
[*Example [1](#class.ctor.general-example-1)*: struct S { S(); // declares the constructor};
|
||
|
||
S::S() { } // defines the constructor â *end example*]
|
||
|
||
[2](#class.ctor.general-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1285)
|
||
|
||
A constructor is used to initialize objects of its class type[.](#class.ctor.general-2.sentence-1)
|
||
|
||
[*Note [1](#class.ctor.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[.](#class.ctor.general-2.sentence-2)
|
||
|
||
The syntax looks like an explicit call of the constructor[.](#class.ctor.general-2.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [2](#class.ctor.general-example-2)*: complex zz = complex(1,2.3);
|
||
cprint( complex(7.8,1.2) ); â *end example*]
|
||
|
||
[*Note [2](#class.ctor.general-note-2)*:
|
||
|
||
For initialization of objects of class type see [[class.init]](class.init "11.9 Initialization")[.](#class.ctor.general-2.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[3](#class.ctor.general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1305)
|
||
|
||
An object created in this way is unnamed[.](#class.ctor.general-3.sentence-1)
|
||
|
||
[*Note [3](#class.ctor.general-note-3)*:
|
||
|
||
[[class.temporary]](class.temporary "6.8.7 Temporary objects") describes the lifetime of temporary objects[.](#class.ctor.general-3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [4](#class.ctor.general-note-4)*:
|
||
|
||
Explicit constructor calls do not yield lvalues, see [[basic.lval]](basic.lval "7.2.1 Value category")[.](#class.ctor.general-3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[4](#class.ctor.general-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1315)
|
||
|
||
[*Note [5](#class.ctor.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")[.](#class.ctor.general-4.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[5](#class.ctor.general-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1322)
|
||
|
||
A constructor can be invoked for aconst,volatile orconstvolatile object[.](#class.ctor.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[.](#class.ctor.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[.](#class.ctor.general-5.sentence-3)
|
||
|
||
[6](#class.ctor.general-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1340)
|
||
|
||
The address of a constructor shall not be taken[.](#class.ctor.general-6.sentence-1)
|
||
|
||
[*Note [6](#class.ctor.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"))[.](#class.ctor.general-6.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[7](#class.ctor.general-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L1349)
|
||
|
||
A constructor shall not be a coroutine[.](#class.ctor.general-7.sentence-1)
|
||
|
||
[8](#class.ctor.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"))[.](#class.ctor.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]) 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]), 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)
|
||
|
||
### [11.4.6](#class.copy.assign) Copy/move assignment operator [[class.copy.assign]](class.copy.assign)
|
||
|
||
[1](#class.copy.assign-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&[.](#class.copy.assign-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](#class.copy.assign-note-1)*:
|
||
|
||
More than one form of copy assignment operator can be declared for a class[.](#class.copy.assign-1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [2](#class.copy.assign-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[.](#class.copy.assign-1.sentence-3)
|
||
|
||
[*Example [1](#class.copy.assign-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](#class.copy.assign-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]")[.](#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"))[.](#class.copy.assign-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"))[.](#class.copy.assign-2.sentence-3)
|
||
|
||
The implicitly-declared copy assignment operator for a classX will have the formX& X::operator=(const X&) if
|
||
|
||
- [(2.1)](#class.copy.assign-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)](#class.copy.assign-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[.](#class.copy.assign-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](#class.copy.assign-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&&[.](#class.copy.assign-3.sentence-1)
|
||
|
||
[*Note [3](#class.copy.assign-note-3)*:
|
||
|
||
More than one form of move assignment operator can be declared for a class[.](#class.copy.assign-3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[4](#class.copy.assign-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)](#class.copy.assign-4.1)
|
||
|
||
X does not have a user-declared copy constructor,
|
||
|
||
- [(4.2)](#class.copy.assign-4.2)
|
||
|
||
X does not have a user-declared move constructor,
|
||
|
||
- [(4.3)](#class.copy.assign-4.3)
|
||
|
||
X does not have a user-declared copy assignment operator, and
|
||
|
||
- [(4.4)](#class.copy.assign-4.4)
|
||
|
||
X does not have a user-declared destructor[.](#class.copy.assign-4.sentence-1)
|
||
|
||
[*Example [2](#class.copy.assign-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[.](#class.copy.assign-4.sentence-2)
|
||
|
||
The move assignment operator may
|
||
be explicitly defaulted[.](#class.copy.assign-4.sentence-3)
|
||
|
||
struct S {int a;
|
||
S& operator=(const S&) = default;
|
||
S& operator=(S&&) = default;}; â *end example*]
|
||
|
||
[5](#class.copy.assign-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](#class.copy.assign-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&[.](#class.copy.assign-6.sentence-1)
|
||
|
||
An implicitly-declared copy/move assignment operator is an
|
||
inline public member of its class[.](#class.copy.assign-6.sentence-2)
|
||
|
||
[7](#class.copy.assign-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)](#class.copy.assign-7.1)
|
||
|
||
a non-static data member of const non-class
|
||
type (or possibly multidimensional array thereof), or
|
||
|
||
- [(7.2)](#class.copy.assign-7.2)
|
||
|
||
a non-static data member of reference type, or
|
||
|
||
- [(7.3)](#class.copy.assign-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[.](#class.copy.assign-7.sentence-1)
|
||
|
||
[*Note [4](#class.copy.assign-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"))[.](#class.copy.assign-7.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[8](#class.copy.assign-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"))[.](#class.copy.assign-8.sentence-1)
|
||
|
||
[*Note [5](#class.copy.assign-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[.](#class.copy.assign-8.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[9](#class.copy.assign-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)](#class.copy.assign-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)](#class.copy.assign-9.2)
|
||
|
||
the assignment operator selected to copy/move each direct
|
||
base class subobject is trivial, and
|
||
|
||
- [(9.3)](#class.copy.assign-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]")[.](#class.copy.assign-9.sentence-1)
|
||
|
||
[10](#class.copy.assign-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[.](#class.copy.assign-10.sentence-1)
|
||
|
||
[11](#class.copy.assign-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[.](#class.copy.assign-11.sentence-1)
|
||
|
||
[*Note [6](#class.copy.assign-note-6)*:
|
||
|
||
An implicitly-declared copy/move assignment operator has an
|
||
implied exception specification ([[except.spec]](except.spec "14.5 Exception specifications"))[.](#class.copy.assign-11.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[12](#class.copy.assign-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[.](#class.copy.assign-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[.](#class.copy.assign-12.sentence-2)
|
||
|
||
Let x be either the parameter of the function or, for the move operator, an
|
||
xvalue referring to the parameter[.](#class.copy.assign-12.sentence-3)
|
||
|
||
Each subobject is assigned in the manner appropriate to its type:
|
||
|
||
- [(12.1)](#class.copy.assign-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)](#class.copy.assign-12.2)
|
||
|
||
if the subobject is an array, each element is assigned,
|
||
in the manner appropriate to the element type;
|
||
|
||
- [(12.3)](#class.copy.assign-12.3)
|
||
|
||
if the subobject is of scalar type,
|
||
the built-in assignment operator is used[.](#class.copy.assign-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[.](#class.copy.assign-12.sentence-5)
|
||
|
||
[*Example [3](#class.copy.assign-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[.](#class.copy.assign-12.sentence-6)
|
||
|
||
â *end example*]
|
||
|
||
[13](#class.copy.assign-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[.](#class.copy.assign-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[.](#class.copy.assign-13.sentence-2)
|
||
|
||
[14](#class.copy.assign-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[.](#class.copy.assign-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)
|
||
|
||
### [11.4.7](#class.dtor) Destructors [[class.dtor]](class.dtor)
|
||
|
||
[1](#class.dtor-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)](#class.dtor-1.1)
|
||
|
||
in a [*member-declaration*](#nt:member-declaration "11.4.1 General [class.mem.general]") that belongs to the[*member-specification*](#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)](#class.dtor-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]")[.](#class.dtor-1.sentence-1)
|
||
|
||
A prospective destructor shall take no arguments ([[dcl.fct]](dcl.fct "9.3.4.6 Functions"))[.](#class.dtor-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[.](#class.dtor-1.sentence-3)
|
||
|
||
[2](#class.dtor-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"))[.](#class.dtor-2.sentence-1)
|
||
|
||
An implicitly-declared prospective destructor is an
|
||
inline public member of its class[.](#class.dtor-2.sentence-2)
|
||
|
||
[3](#class.dtor-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](#class.dtor-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]")[.](#class.dtor-4.sentence-1)
|
||
|
||
The program is ill-formed if overload resolution fails[.](#class.dtor-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"))[.](#class.dtor-4.sentence-3)
|
||
|
||
[5](#class.dtor-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2151)
|
||
|
||
The address of a destructor shall not be taken[.](#class.dtor-5.sentence-1)
|
||
|
||
[*Note [1](#class.dtor-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"))[.](#class.dtor-5.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
A destructor can be invoked for aconst,volatile orconstvolatile object[.](#class.dtor-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[.](#class.dtor-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[.](#class.dtor-5.sentence-5)
|
||
|
||
[6](#class.dtor-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2175)
|
||
|
||
[*Note [2](#class.dtor-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"))[.](#class.dtor-6.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[7](#class.dtor-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)](#class.dtor-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)](#class.dtor-7.2)
|
||
|
||
X is a union and
|
||
* [(7.2.1)](#class.dtor-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)](#class.dtor-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)](#class.dtor-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[.](#class.dtor-7.sentence-1)
|
||
|
||
[8](#class.dtor-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)](#class.dtor-8.1)
|
||
|
||
the destructor is not virtual,
|
||
|
||
- [(8.2)](#class.dtor-8.2)
|
||
|
||
all of the direct base classes of X have trivial destructors, and
|
||
|
||
- [(8.3)](#class.dtor-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[.](#class.dtor-8.sentence-1)
|
||
|
||
Otherwise, the destructor is[*non-trivial*](#def:destructor,non-trivial "11.4.7 Destructors [class.dtor]")[.](#class.dtor-8.sentence-2)
|
||
|
||
[9](#class.dtor-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"))[.](#class.dtor-9.sentence-1)
|
||
|
||
[10](#class.dtor-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[.](#class.dtor-10.sentence-1)
|
||
|
||
[11](#class.dtor-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*](#nt:pure-specifier "11.4.1 General [class.mem.general]") ([[class.abstract]](class.abstract "11.7.4 Abstract classes"))[.](#class.dtor-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[.](#class.dtor-11.sentence-2)
|
||
|
||
[12](#class.dtor-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2245)
|
||
|
||
[*Note [3](#class.dtor-note-3)*:
|
||
|
||
Some language constructs have special semantics when used during destruction;
|
||
see [[class.cdtor]](class.cdtor "11.9.5 Construction and destruction")[.](#class.dtor-12.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[13](#class.dtor-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[.](#class.dtor-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[.](#class.dtor-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"))[.](#class.dtor-13.sentence-3)
|
||
|
||
[*Note [4](#class.dtor-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[.](#class.dtor-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"))[.](#class.dtor-13.sentence-5)
|
||
|
||
[14](#class.dtor-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2287)
|
||
|
||
A destructor is invoked implicitly
|
||
|
||
- [(14.1)](#class.dtor-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)](#class.dtor-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)](#class.dtor-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)](#class.dtor-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"))[.](#class.dtor-14.sentence-1)
|
||
|
||
In each case, the context of the invocation is the context of the construction of
|
||
the object[.](#class.dtor-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]")[.](#class.dtor-14.sentence-3)
|
||
|
||
[*Note [5](#class.dtor-note-5)*:
|
||
|
||
An array of class type contains several subobjects for each of which
|
||
the destructor is invoked[.](#class.dtor-14.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
A destructor can also be invoked explicitly[.](#class.dtor-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")[.](#class.dtor-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[.](#class.dtor-14.sentence-7)
|
||
|
||
[15](#class.dtor-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"))[.](#class.dtor-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[.](#class.dtor-15.sentence-2)
|
||
|
||
[*Note [6](#class.dtor-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"))[.](#class.dtor-15.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[16](#class.dtor-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[.](#class.dtor-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[.](#class.dtor-16.sentence-2)
|
||
|
||
[*Note [7](#class.dtor-note-7)*:
|
||
|
||
Invoking delete on a null pointer does not call the
|
||
destructor; see [[expr.delete]](expr.delete "7.6.2.9 Delete")[.](#class.dtor-16.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#class.dtor-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](#class.dtor-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"))[.](#class.dtor-16.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[17](#class.dtor-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2380)
|
||
|
||
[*Note [9](#class.dtor-note-9)*:
|
||
|
||
Explicit calls of destructors are rarely needed[.](#class.dtor-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]")[.](#class.dtor-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[.](#class.dtor-17.sentence-3)
|
||
|
||
[*Example [2](#class.dtor-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](#class.dtor-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"))[.](#class.dtor-18.sentence-1)
|
||
|
||
[*Example [3](#class.dtor-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[.](#class.dtor-18.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[19](#class.dtor-19)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2419)
|
||
|
||
[*Note [10](#class.dtor-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"))[.](#class.dtor-19.sentence-1)
|
||
|
||
Allowing this makes it possible to write code without having to know if a
|
||
destructor exists for a given type[.](#class.dtor-19.sentence-2)
|
||
|
||
For example:typedef int I;
|
||
I* p;
|
||
p->I::~I();
|
||
|
||
â *end note*]
|
||
|
||
[20](#class.dtor-20)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2434)
|
||
|
||
A destructor shall not be a coroutine[.](#class.dtor-20.sentence-1)
|
||
|
||
### [11.4.8](#class.conv) Conversions [[class.conv]](class.conv)
|
||
|
||
#### [11.4.8.1](#class.conv.general) General [[class.conv.general]](class.conv.general)
|
||
|
||
[1](#class.conv.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[.](#class.conv.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"))[.](#class.conv.general-1.sentence-2)
|
||
|
||
[2](#class.conv.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]](#class.conv.fct "11.4.8.3 Conversion functions"))[.](#class.conv.general-2.sentence-1)
|
||
|
||
Conversions obey the access control rules ([[class.access]](class.access "11.8 Member access control"))[.](#class.conv.general-2.sentence-2)
|
||
|
||
Access control is applied after ambiguity resolution ([[basic.lookup]](basic.lookup "6.5 Name lookup"))[.](#class.conv.general-2.sentence-3)
|
||
|
||
[3](#class.conv.general-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2460)
|
||
|
||
[*Note [1](#class.conv.general-note-1)*:
|
||
|
||
See [[over.match]](over.match "12.2 Overload resolution") for a discussion of the use of conversions in function calls[.](#class.conv.general-3.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[4](#class.conv.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[.](#class.conv.general-4.sentence-1)
|
||
|
||
[*Example [1](#class.conv.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](#class.conv.ctor) Conversion by constructor [[class.conv.ctor]](class.conv.ctor)
|
||
|
||
[1](#class.conv.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[.](#class.conv.ctor-1.sentence-1)
|
||
|
||
[*Example [1](#class.conv.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](#class.conv.ctor-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2512)
|
||
|
||
[*Note [1](#class.conv.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")[.](#class.conv.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"))[.](#class.conv.ctor-2.sentence-2)
|
||
|
||
[*Example [2](#class.conv.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](#class.conv.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](#class.conv.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)](#class.conv.fct-1.1)
|
||
|
||
in a [*member-declaration*](#nt:member-declaration "11.4.1 General [class.mem.general]") that belongs to
|
||
the [*member-specification*](#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)](#class.conv.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]")[.](#class.conv.fct-1.sentence-1)
|
||
|
||
[2](#class.conv.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"))[.](#class.conv.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]")[.](#class.conv.fct-2.sentence-2)
|
||
|
||
[3](#class.conv.fct-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2600)
|
||
|
||
[*Note [1](#class.conv.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[.](#class.conv.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[.](#class.conv.fct-3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#class.conv.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()[.](#class.conv.fct-3.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
[4](#class.conv.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"))[.](#class.conv.fct-4.sentence-1)
|
||
|
||
Otherwise, user-defined conversions are not restricted to use in assignments and initializations[.](#class.conv.fct-4.sentence-2)
|
||
|
||
[*Example [2](#class.conv.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](#class.conv.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[.](#class.conv.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]")[.](#class.conv.fct-5.sentence-2)
|
||
|
||
[*Note [2](#class.conv.fct-note-2)*:
|
||
|
||
This prevents ambiguities between the declarator operator * and its expression
|
||
counterparts[.](#class.conv.fct-5.sentence-3)
|
||
|
||
[*Example [3](#class.conv.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[.](#class.conv.fct-5.sentence-4)
|
||
|
||
â *end example*]
|
||
|
||
This rule also prevents ambiguities for attributes[.](#class.conv.fct-5.sentence-5)
|
||
|
||
[*Example [4](#class.conv.fct-example-4)*: operator int [[noreturn]] (); // error: noreturn attribute applied to a type â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[6](#class.conv.fct-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2681)
|
||
|
||
[*Note [3](#class.conv.fct-note-3)*:
|
||
|
||
A conversion function in a derived class hides only
|
||
conversion functions in base classes that convert to the same type[.](#class.conv.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[.](#class.conv.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[.](#class.conv.fct-6.sentence-3)
|
||
|
||
[*Example [5](#class.conv.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](#class.conv.fct-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2709)
|
||
|
||
Conversion functions can be virtual[.](#class.conv.fct-7.sentence-1)
|
||
|
||
[8](#class.conv.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"))[.](#class.conv.fct-8.sentence-1)
|
||
|
||
[*Example [6](#class.conv.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*]
|
||
|
||
### [11.4.9](#class.static) Static members [[class.static]](class.static)
|
||
|
||
#### [11.4.9.1](#class.static.general) General [[class.static.general]](class.static.general)
|
||
|
||
[1](#class.static.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[.](#class.static.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[.](#class.static.general-1.sentence-2)
|
||
|
||
[*Example [1](#class.static.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](#class.static.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"))[.](#class.static.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*](#nt:member-specification "11.4.1 General [class.mem.general]") of
|
||
the class definition[.](#class.static.general-2.sentence-2)
|
||
|
||
[*Note [1](#class.static.general-note-1)*:
|
||
|
||
It cannot be specified in member declarations that appear in namespace scope[.](#class.static.general-2.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
#### [11.4.9.2](#class.static.mfct) Static member functions [[class.static.mfct]](class.static.mfct)
|
||
|
||
[1](#class.static.mfct-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2766)
|
||
|
||
[*Note [1](#class.static.mfct-note-1)*:
|
||
|
||
The rules described in [[class.mfct]](#class.mfct "11.4.2 Member functions") apply to static member
|
||
functions[.](#class.static.mfct-1.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[2](#class.static.mfct-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2772)
|
||
|
||
[*Note [2](#class.static.mfct-note-2)*:
|
||
|
||
A static member function does not have a this pointer ([[expr.prim.this]](expr.prim.this "7.5.3 This"))[.](#class.static.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"))[.](#class.static.mfct-2.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
#### [11.4.9.3](#class.static.data) Static data members [[class.static.data]](class.static.data)
|
||
|
||
[1](#class.static.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[.](#class.static.data-1.sentence-1)
|
||
|
||
If a
|
||
static data member is declared thread_local there is one copy of
|
||
the member per thread[.](#class.static.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[.](#class.static.data-1.sentence-3)
|
||
|
||
[2](#class.static.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"))[.](#class.static.data-2.sentence-1)
|
||
|
||
A static data member shall not be a direct member ([class.mem])
|
||
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[.](#class.static.data-2.sentence-2)
|
||
|
||
[3](#class.static.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[.](#class.static.data-3.sentence-1)
|
||
|
||
[*Note [1](#class.static.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"))[.](#class.static.data-3.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#class.static.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[.](#class.static.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[.](#class.static.data-3.sentence-4)
|
||
|
||
â *end example*]
|
||
|
||
[*Note [2](#class.static.data-note-2)*:
|
||
|
||
Once the static data member has been defined, it exists even if
|
||
no objects of its class have been created[.](#class.static.data-3.sentence-5)
|
||
|
||
[*Example [2](#class.static.data-example-2)*:
|
||
|
||
In the example above, run_chain and running exist even
|
||
if no objects of class process are created by the program[.](#class.static.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")[.](#class.static.data-3.sentence-7)
|
||
|
||
â *end note*]
|
||
|
||
[4](#class.static.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"))[.](#class.static.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]")[.](#class.static.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]")[.](#class.static.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"))[.](#class.static.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]")[.](#class.static.data-4.sentence-5)
|
||
|
||
[5](#class.static.data-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2857)
|
||
|
||
[*Note [3](#class.static.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[.](#class.static.data-5.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[6](#class.static.data-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2863)
|
||
|
||
[*Note [4](#class.static.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"))[.](#class.static.data-6.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
### [11.4.10](#class.bit) Bit-fields [[class.bit]](class.bit)
|
||
|
||
[1](#class.bit-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2871)
|
||
|
||
A [*member-declarator*](#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[.](#class.bit-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[.](#class.bit-1.sentence-2)
|
||
|
||
A bit-field shall not be a static member[.](#class.bit-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[.](#class.bit-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[.](#class.bit-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"))[.](#class.bit-1.sentence-6)
|
||
|
||
Allocation of bit-fields within a class object isimplementation-defined[.](#class.bit-1.sentence-7)
|
||
|
||
Alignment of bit-fields is implementation-defined[.](#class.bit-1.sentence-8)
|
||
|
||
Bit-fields are packed into some addressable allocation unit[.](#class.bit-1.sentence-9)
|
||
|
||
[*Note [1](#class.bit-note-1)*:
|
||
|
||
Bit-fields straddle allocation units on some machines and not on others[.](#class.bit-1.sentence-10)
|
||
|
||
Bit-fields are assigned right-to-left on some machines, left-to-right on
|
||
others[.](#class.bit-1.sentence-11)
|
||
|
||
â *end note*]
|
||
|
||
[2](#class.bit-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]")[.](#class.bit-2.sentence-1)
|
||
|
||
Unnamed bit-fields are not
|
||
members and cannot be initialized[.](#class.bit-2.sentence-2)
|
||
|
||
An unnamed bit-field shall not be declared with a cv-qualified type[.](#class.bit-2.sentence-3)
|
||
|
||
[*Note [2](#class.bit-note-2)*:
|
||
|
||
An unnamed bit-field is useful for padding to conform to
|
||
externally-imposed layouts[.](#class.bit-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[.](#class.bit-2.sentence-5)
|
||
|
||
Only
|
||
when declaring an unnamed bit-field may the width be zero[.](#class.bit-2.sentence-6)
|
||
|
||
[3](#class.bit-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[.](#class.bit-3.sentence-1)
|
||
|
||
A non-const reference shall not bind to a bit-field ([[dcl.init.ref]](dcl.init.ref "9.5.4 References"))[.](#class.bit-3.sentence-2)
|
||
|
||
[*Note [3](#class.bit-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[.](#class.bit-3.sentence-3)
|
||
|
||
See [[dcl.init.ref]](dcl.init.ref "9.5.4 References")[.](#class.bit-3.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[4](#class.bit-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[.](#class.bit-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[.](#class.bit-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[.](#class.bit-4.sentence-3)
|
||
|
||
[*Example [1](#class.bit-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*]
|
||
|
||
### [11.4.11](#class.free) Allocation and deallocation functions [[class.free]](class.free)
|
||
|
||
[1](#class.free-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)[.](#class.free-1.sentence-1)
|
||
|
||
[2](#class.free-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L2974)
|
||
|
||
[*Example [1](#class.free-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](#class.free-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)[.](#class.free-3.sentence-1)
|
||
|
||
[*Example [2](#class.free-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](#class.free-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3014)
|
||
|
||
Since member allocation and deallocation functions arestatic they cannot be virtual[.](#class.free-4.sentence-1)
|
||
|
||
[*Note [1](#class.free-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[.](#class.free-4.sentence-2)
|
||
|
||
[*Example [3](#class.free-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[.](#class.free-4.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
â *end note*]
|
||
|
||
[*Note [2](#class.free-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[.](#class.free-4.sentence-4)
|
||
|
||
[*Example [4](#class.free-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](#class.free-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[.](#class.free-5.sentence-1)
|
||
|
||
[*Example [5](#class.free-example-5)*:
|
||
|
||
For the call on line â// 1â above,
|
||
ifB::operator delete() had been private, the delete expression would have been ill-formed[.](#class.free-5.sentence-2)
|
||
|
||
â *end example*]
|
||
|
||
[6](#class.free-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3102)
|
||
|
||
[*Note [3](#class.free-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"))[.](#class.free-6.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
### [11.4.12](#class.nest) Nested class declarations [[class.nest]](class.nest)
|
||
|
||
[1](#class.nest-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3111)
|
||
|
||
A class can be declared within another class[.](#class.nest-1.sentence-1)
|
||
|
||
A class declared within
|
||
another is called a [*nested class*](#def:class,nested "11.4.12 Nested class declarations [class.nest]")[.](#class.nest-1.sentence-2)
|
||
|
||
[*Note [1](#class.nest-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[.](#class.nest-1.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[*Example [1](#class.nest-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](#class.nest-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/classes.tex#L3146)
|
||
|
||
[*Note [2](#class.nest-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[.](#class.nest-2.sentence-1)
|
||
|
||
[*Example [2](#class.nest-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](#class.nest-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[.](#class.nest-3.sentence-1)
|