Files
2025-10-25 03:02:53 +03:00

793 lines
39 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

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

[dcl.fct.def]
# 9 Declarations [[dcl]](./#dcl)
## 9.6 Function definitions [dcl.fct.def]
### [9.6.1](#general) General [[dcl.fct.def.general]](dcl.fct.def.general)
[1](#general-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6827)
Function definitions have the form
[function-definition:](#nt:function-definition "9.6.1General[dcl.fct.def.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1General[class.mem.general]")opt
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")
[*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]")opt [*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]")opt [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]")
[*function-contract-specifier-seq*](dcl.contract.func#nt:function-contract-specifier-seq "9.4.1General[dcl.contract.func]")opt [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")
[function-body:](#nt:function-body "9.6.1General[dcl.fct.def.general]")
[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]")opt [*compound-statement*](stmt.block#nt:compound-statement "8.4Compound statement or block[stmt.block]")
[*function-try-block*](except.pre#nt:function-try-block "14.1Preamble[except.pre]")
= default ;
[*deleted-function-body*](#nt:deleted-function-body "9.6.1General[dcl.fct.def.general]")
[deleted-function-body:](#nt:deleted-function-body "9.6.1General[dcl.fct.def.general]")
= delete ;
= delete ( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]") ) ;
Any informal reference to the body of a function should be interpreted as a reference to
the non-terminal [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]"),
including, for a constructor,
default member initializers or default initialization
used to initialize
a base or member subobject in the absence of
a [*mem-initializer-id*](class.base.init#nt:mem-initializer-id "11.9.3Initializing bases and members[class.base.init]") ([[class.base.init]](class.base.init "11.9.3Initializing bases and members"))[.](#general-1.sentence-2)
The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1Attribute syntax and semantics[dcl.attr.grammar]") in a [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") appertains to the function[.](#general-1.sentence-3)
A [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") with a [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1General[class.mem.general]") shall be a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1General[class.mem.general]") ([[class.mem]](class.mem "11.4Class members"))[.](#general-1.sentence-4)
A [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") with a [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") shall define a templated function[.](#general-1.sentence-5)
[2](#general-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6868)
In a [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]"),
either void [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") ; or [*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]") ; shall be a well-formed function declaration
as described in [[dcl.fct]](dcl.fct "9.3.4.6Functions")[.](#general-2.sentence-1)
A function shall be defined only in namespace or class scope[.](#general-2.sentence-2)
The type of a parameter or the return type for a function
definition shall not be
a (possibly cv-qualified) class type that is
incomplete or abstract within the function body
unless the function is deleted ([[dcl.fct.def.delete]](#delete "9.6.3Deleted definitions"))[.](#general-2.sentence-3)
[3](#general-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6881)
[*Example [1](#general-example-1)*:
A simple example of a complete function definition isint max(int a, int b, int c) {int m = (a > b) ? a : b; return (m > c) ? m : c;}
Hereint is the[*decl-specifier-seq*](dcl.spec.general#nt:decl-specifier-seq "9.2.1General[dcl.spec.general]");max(inta,intb,intc) is the[*declarator*](dcl.decl.general#nt:declarator "9.3.1General[dcl.decl.general]");{ /* ... */ } is the[*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")[.](#general-3.sentence-2)
— *end example*]
[4](#general-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6908)
A[*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3Initializing bases and members[class.base.init]") is used only in a constructor; see [[class.ctor]](class.ctor "11.4.5Constructors") and [[class.init]](class.init "11.9Initialization")[.](#general-4.sentence-1)
[5](#general-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6916)
[*Note [1](#general-note-1)*:
A [*cv-qualifier-seq*](dcl.decl.general#nt:cv-qualifier-seq "9.3.1General[dcl.decl.general]") affects the type of this in the body of a member function; see [[expr.prim.this]](expr.prim.this "7.5.3This")[.](#general-5.sentence-1)
— *end note*]
[6](#general-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6922)
[*Note [2](#general-note-2)*:
Unused parameters need not be named[.](#general-6.sentence-1)
For example,
void print(int a, int) { std::printf("a = %d\n",a);} — *end note*]
[7](#general-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6934)
A [*function-local predefined variable*](#def:variable,function-local_predefined "9.6.1General[dcl.fct.def.general]") is a variable with static
storage duration that is implicitly defined in a function parameter scope[.](#general-7.sentence-1)
[8](#general-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6938)
The function-local predefined variable __func__ is
defined as if a definition of the formstatic const char __func__[] = "*function-name*"; had been provided, where *function-name* is an implementation-defined string[.](#general-8.sentence-1)
It is unspecified whether such a variable has an address
distinct from that of any other object in the program[.](#general-8.sentence-2)[81](#footnote-81 "Implementations are permitted to provide additional predefined variables with names that are reserved to the implementation ([lex.name]). If a predefined variable is not odr-used ([term.odr.use]), its string value need not be present in the program image.")
[*Example [2](#general-example-2)*: struct S { S() : s(__func__) { } // OKconst char* s;};void f(const char* s = __func__); // error: __func__ is undeclared — *end example*]
[81)](#footnote-81)[81)](#footnoteref-81)
Implementations are
permitted to provide additional predefined variables with names that are reserved to the
implementation ([[lex.name]](lex.name "5.11Identifiers"))[.](#footnote-81.sentence-1)
If a predefined variable is not
odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")), its string value need not be present in the program image[.](#footnote-81.sentence-2)
### [9.6.2](#default) Explicitly-defaulted functions [[dcl.fct.def.default]](dcl.fct.def.default)
[1](#default-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6967)
A function definition whose[*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]") is of the form= default ; is called an [*explicitly-defaulted*](#def:definition,function,explicitly-defaulted "9.6.2Explicitly-defaulted functions[dcl.fct.def.default]") definition[.](#default-1.sentence-1)
A function that is explicitly defaulted shall
- [(1.1)](#default-1.1)
be a special member function ([[special]](special "11.4.4Special member functions")) or
a comparison operator function ([[over.binary]](over.binary "12.4.3Binary operators"), [[class.compare.default]](class.compare.default "11.10.1Defaulted comparison operator functions")), and
- [(1.2)](#default-1.2)
not have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7Default arguments"))[.](#default-1.sentence-2)
[2](#default-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L6980)
An explicitly defaulted special member function F1 is allowed to differ from
the corresponding special member function F2 that would have been implicitly declared, as follows:
- [(2.1)](#default-2.1)
F1 and F2 may have differing [*ref-qualifier*](dcl.decl.general#nt:ref-qualifier "9.3.1General[dcl.decl.general]")*s*;
- [(2.2)](#default-2.2)
if F2 has an implicit object parameter of
type “reference to C”, F1 may be an explicit object member function whose
explicit object parameter is of (possibly different) type “reference to C”,
in which case the type of F1 would differ from the type of F2 in that the type of F1 has an additional parameter;
- [(2.3)](#default-2.3)
F1 and F2 may have differing exception specifications; and
- [(2.4)](#default-2.4)
if F2 has a non-object parameter of type const C&,
the corresponding non-object parameter of F1 may be of
type C&[.](#default-2.sentence-1)
If the type of F1 differs from the type of F2 in a way
other than as allowed by the preceding rules, then:
- [(2.5)](#default-2.5)
if F1 is an assignment operator, and
the return type of F1 differs from
the return type of F2 or F1's non-object parameter type is not a reference,
the program is ill-formed;
- [(2.6)](#default-2.6)
otherwise, if F1 is explicitly defaulted on its first declaration,
it is defined as deleted;
- [(2.7)](#default-2.7)
otherwise, the program is ill-formed[.](#default-2.sentence-2)
[3](#default-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7018)
A function explicitly defaulted on its first declaration
is implicitly inline ([[dcl.inline]](dcl.inline "9.2.8The inline specifier")),
and is implicitly constexpr ([[dcl.constexpr]](dcl.constexpr "9.2.6The constexpr and consteval specifiers"))
if it is constexpr-suitable[.](#default-3.sentence-1)
[*Note [1](#default-note-1)*:
Other defaulted functions are not implicitly constexpr[.](#default-3.sentence-2)
— *end note*]
[4](#default-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7027)
[*Example [1](#default-example-1)*: struct S { S(int a = 0) = default; // error: default argumentvoid operator=(const S&) = default; // error: non-matching return type~S() noexcept(false) = default; // OK, despite mismatched exception specificationprivate:int i;
S(S&); // OK, private copy constructor};
S::S(S&) = default; // OK, defines copy constructorstruct T { T();
T(T &&) noexcept(false);};struct U { T t;
U();
U(U &&) noexcept = default;};
U u1;
U u2 = static_cast<U&&>(u1); // OK, calls std::terminate if T::T(T&&) throws — *end example*]
[5](#default-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7054)
Explicitly-defaulted functions and implicitly-declared functions are collectively
called [*defaulted*](#def:defaulted "9.6.2Explicitly-defaulted functions[dcl.fct.def.default]") functions, and the implementation
shall provide implicit definitions
for them ([[class.ctor]](class.ctor "11.4.5Constructors"), [[class.dtor]](class.dtor "11.4.7Destructors"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3Copy/move constructors"), [[class.copy.assign]](class.copy.assign "11.4.6Copy/move assignment operator")) as described below,
including possibly defining them as deleted[.](#default-5.sentence-1)
A defaulted prospective destructor ([[class.dtor]](class.dtor "11.4.7Destructors"))
that is not a destructor is defined as deleted[.](#default-5.sentence-2)
A defaulted special member function
that is neither a prospective destructor nor
an eligible special member function ([[special]](special "11.4.4Special member functions"))
is defined as deleted[.](#default-5.sentence-3)
A function is[*user-provided*](#def:user-provided "9.6.2Explicitly-defaulted functions[dcl.fct.def.default]") if it is user-declared and not explicitly
defaulted or deleted on its first declaration[.](#default-5.sentence-4)
A user-provided explicitly-defaulted function
(i.e., explicitly defaulted after its first declaration)
is implicitly defined at the point where it is explicitly defaulted; if such a function is implicitly
defined as deleted, the program is ill-formed[.](#default-5.sentence-5)
[*Note [2](#default-note-2)*:
Declaring a function as defaulted after its first declaration
can provide efficient execution and concise definition
while enabling a stable binary interface to an evolving code base[.](#default-5.sentence-6)
— *end note*]
A non-user-provided defaulted function
(i.e., implicitly declared or explicitly defaulted in the class)
that is not defined as deleted is implicitly defined when it is odr-used ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
or needed for constant evaluation ([[expr.const]](expr.const "7.7Constant expressions"))[.](#default-5.sentence-7)
[*Note [3](#default-note-3)*:
The implicit definition of a non-user-provided defaulted function
does not bind any names[.](#default-5.sentence-8)
— *end note*]
[6](#default-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7086)
[*Example [2](#default-example-2)*: struct trivial { trivial() = default;
trivial(const trivial&) = default;
trivial(trivial&&) = default;
trivial& operator=(const trivial&) = default;
trivial& operator=(trivial&&) = default; ~trivial() = default;};
struct nontrivial1 { nontrivial1();};
nontrivial1::nontrivial1() = default; // not first declaration — *end example*]
### [9.6.3](#delete) Deleted definitions [[dcl.fct.def.delete]](dcl.fct.def.delete)
[1](#delete-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7108)
A [*deleted definition*](#def:definition,deleted "9.6.3Deleted definitions[dcl.fct.def.delete]") of a function is a function definition
whose [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]") is a [*deleted-function-body*](#nt:deleted-function-body "9.6.1General[dcl.fct.def.general]") or an explicitly-defaulted definition of the function where the function is
defined as deleted[.](#delete-1.sentence-1)
A [*deleted function*](#def:function,deleted "9.6.3Deleted definitions[dcl.fct.def.delete]") is
a function with a
deleted definition or a function that is implicitly defined as deleted[.](#delete-1.sentence-2)
[2](#delete-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7117)
A construct that designates a deleted function implicitly or explicitly,
other than to declare it or to appear as the operand of
a [*reflect-expression*](expr.reflect#nt:reflect-expression "7.6.2.10The reflection operator[expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10The reflection operator")),
is ill-formed[.](#delete-2.sentence-1)
*Recommended practice*: The resulting diagnostic message should include
the text of the [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]"),
if one is supplied[.](#delete-2.sentence-2)
[*Note [1](#delete-note-1)*:
This includes calling the function
implicitly or explicitly and forming a pointer or pointer-to-member to the
function[.](#delete-2.sentence-3)
It applies even for references in expressions that are not
potentially-evaluated[.](#delete-2.sentence-4)
For an overload set, only the
function selected by overload resolution is referenced[.](#delete-2.sentence-5)
The implicit
odr-use ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3One-definition rule")) of a virtual function does not, by itself,
constitute a reference[.](#delete-2.sentence-6)
The [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6Unevaluated strings[lex.string.uneval]"), if present,
can be used to explain the rationale for deletion and/or
to suggest an alternative[.](#delete-2.sentence-7)
— *end note*]
[3](#delete-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7141)
[*Example [1](#delete-example-1)*:
One can prevent default initialization and
initialization by non-doubles withstruct onlydouble { onlydouble() = delete; // OK, but redundanttemplate<class T> onlydouble(T) = delete;
onlydouble(double);};
— *end example*]
[*Example [2](#delete-example-2)*:
One can prevent use of a
class in certain [*new-expression*](expr.new#nt:new-expression "7.6.2.8New[expr.new]")*s* by using deleted definitions
of a user-declared operator new for that class[.](#delete-3.sentence-2)
struct sometype {void* operator new(std::size_t) = delete; void* operator new[](std::size_t) = delete;};
sometype* p = new sometype; // error: deleted class operator new sometype* q = new sometype[3]; // error: deleted class operator new[] — *end example*]
[*Example [3](#delete-example-3)*:
One can make a class uncopyable, i.e., move-only, by using deleted
definitions of the copy constructor and copy assignment operator, and then
providing defaulted definitions of the move constructor and move assignment operator[.](#delete-3.sentence-3)
struct moveonly { moveonly() = default;
moveonly(const moveonly&) = delete;
moveonly(moveonly&&) = default;
moveonly& operator=(const moveonly&) = delete;
moveonly& operator=(moveonly&&) = default; ~moveonly() = default;};
moveonly* p;
moveonly q(*p); // error: deleted copy constructor — *end example*]
[4](#delete-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7187)
A deleted function is implicitly an inline function ([[dcl.inline]](dcl.inline "9.2.8The inline specifier"))[.](#delete-4.sentence-1)
[*Note [2](#delete-note-2)*:
The
one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule")) applies to deleted definitions[.](#delete-4.sentence-2)
— *end note*]
A deleted definition of a function shall be the first declaration of the function or,
for an explicit specialization of a function template, the first declaration of that
specialization[.](#delete-4.sentence-3)
An implicitly declared allocation or deallocation function ([[basic.stc.dynamic]](basic.stc.dynamic "6.8.6.5Dynamic storage duration"))
shall not be defined as deleted[.](#delete-4.sentence-4)
[*Example [4](#delete-example-4)*: struct sometype { sometype();};
sometype::sometype() = delete; // error: not first declaration — *end example*]
### [9.6.4](#coroutine) Coroutine definitions [[dcl.fct.def.coroutine]](dcl.fct.def.coroutine)
[1](#coroutine-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7211)
A function is a [*coroutine*](#def:coroutine "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") if its [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]") encloses a[*coroutine-return-statement*](stmt.return.coroutine#nt:coroutine-return-statement "8.8.5The co_­return statement[stmt.return.coroutine]") ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5The co_­return statement")),
an [*await-expression*](expr.await#nt:await-expression "7.6.2.4Await[expr.await]") ([[expr.await]](expr.await "7.6.2.4Await")),
or a [*yield-expression*](expr.yield#nt:yield-expression "7.6.17Yielding a value[expr.yield]") ([[expr.yield]](expr.yield "7.6.17Yielding a value"))[.](#coroutine-1.sentence-1)
The [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6Functions[dcl.fct]") of the coroutine shall not
terminate with an ellipsis that is not part of
a [*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")[.](#coroutine-1.sentence-2)
[2](#coroutine-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7220)
[*Example [1](#coroutine-example-1)*: task<int> f();
task<void> g1() {int i = co_await f();
std::cout << "f() => " << i << std::endl;}template <typename... Args> task<void> g2(Args&&...) { // OK, ellipsis is a pack expansionint i = co_await f();
std::cout << "f() => " << i << std::endl;} task<void> g3(int a, ...) { // error: variable parameter list not allowedint i = co_await f();
std::cout << "f() => " << i << std::endl;} — *end example*]
[3](#coroutine-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7243)
The [*promise type*](#def:coroutine,promise_type "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") of a coroutine isstd::coroutine_traits<R, P1, …, Pn>::promise_type,
whereR is the return type of the function, andP1…Pn is the sequence of types of the non-object function parameters,
preceded by the type of the object parameter ([[dcl.fct]](dcl.fct "9.3.4.6Functions"))
if the coroutine is a non-static member function[.](#coroutine-3.sentence-1)
The promise type shall be a class type[.](#coroutine-3.sentence-2)
[4](#coroutine-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7254)
In the following, pi is an lvalue of type Pi,
wherep1 denotes the object parameter andpi+1 denotes the ith non-object function parameter
for an implicit object member function, andpi denotes
the ith function parameter otherwise[.](#coroutine-4.sentence-1)
For an implicit object member function,q1 is an lvalue that denotes *this;
any other qi is an lvalue
that denotes the parameter copy corresponding to pi,
as described below[.](#coroutine-4.sentence-2)
[5](#coroutine-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7268)
A coroutine behaves as if
the top-level cv-qualifiers in all[*parameter-declaration*](dcl.fct#nt:parameter-declaration "9.3.4.6Functions[dcl.fct]")*s* in the declarator
of its [*function-definition*](#nt:function-definition "9.6.1General[dcl.fct.def.general]") were removed and
its [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]") were replaced by
the following [*replacement body*](#def:body,replacement "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"):
{
*promise-type* *promise* *promise-constructor-arguments* ;
try {
co_await *promise*.initial_suspend() ;
[*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]")
} catch ( ... ) {
if (!*initial-await-resume-called*)
throw ;
*promise*.unhandled_exception() ;
}
*final-suspend* :
co_await *promise*.final_suspend() ;
}
where
- [(5.1)](#coroutine-5.1)
the [*await-expression*](expr.await#nt:await-expression "7.6.2.4Await[expr.await]") containing
the call to initial_suspend is the [*initial await expression*](#def:await_expression,initial "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"), and
- [(5.2)](#coroutine-5.2)
the [*await-expression*](expr.await#nt:await-expression "7.6.2.4Await[expr.await]") containing
the call to final_suspend is the [*final await expression*](#def:await_expression,final "9.6.4Coroutine definitions[dcl.fct.def.coroutine]"), and
- [(5.3)](#coroutine-5.3)
*initial-await-resume-called* is initially false and is set to true immediately before the evaluation
of the *await-resume* expression ([[expr.await]](expr.await "7.6.2.4Await"))
of the initial await expression, and
- [(5.4)](#coroutine-5.4)
*promise-type* denotes the promise type, and
- [(5.5)](#coroutine-5.5)
the object denoted by the exposition-only name *promise* is the [*promise object*](#def:promise_object "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") of the coroutine, and
- [(5.6)](#coroutine-5.6)
the label denoted by the name *final-suspend* is defined for exposition only ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5The co_­return statement")), and
- [(5.7)](#coroutine-5.7)
*promise-constructor-arguments* is determined as follows:
overload resolution is performed on a promise constructor call created by
assembling an argument list q1…qn[.](#coroutine-5.7.sentence-1)
If a viable
constructor is found ([[over.match.viable]](over.match.viable "12.2.3Viable functions")), then*promise-constructor-arguments* is(q1, …, qn), otherwise*promise-constructor-arguments* is empty, and
- [(5.8)](#coroutine-5.8)
a coroutine is suspended at the [*initial suspend point*](#def:suspend_point,initial "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") if
it is suspended at the initial await expression, and
- [(5.9)](#coroutine-5.9)
a coroutine is suspended at a [*final suspend point*](#def:suspend_point,final "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") if
it is suspended
* [(5.9.1)](#coroutine-5.9.1)
at a final await expression or
* [(5.9.2)](#coroutine-5.9.2)
due to an exception exiting from unhandled_exception()[.](#coroutine-5.9.sentence-1)
[6](#coroutine-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7340)
[*Note [1](#coroutine-note-1)*:
An odr-use of a non-reference parameter
in a postcondition assertion
of a coroutine is ill-formed ([[dcl.contract.func]](dcl.contract.func "9.4.1General"))[.](#coroutine-6.sentence-1)
— *end note*]
[7](#coroutine-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7347)
If searches for the names return_void and return_value in the scope of the promise type each find any declarations,
the program is ill-formed[.](#coroutine-7.sentence-1)
[*Note [2](#coroutine-note-2)*:
If return_void is found, flowing off
the end of a coroutine is equivalent to a co_return with no operand[.](#coroutine-7.sentence-2)
Otherwise, flowing off the end of a coroutine
results in undefined behavior ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5The co_­return statement"))[.](#coroutine-7.sentence-3)
— *end note*]
[8](#coroutine-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7358)
The expression *promise*.get_return_object() is used
to initialize
the returned reference or prvalue result object of a call to a coroutine[.](#coroutine-8.sentence-1)
The call to get_return_object is sequenced before
the call to initial_suspend and is invoked at most once[.](#coroutine-8.sentence-2)
[9](#coroutine-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7367)
A suspended coroutine can be resumed to continue execution by invoking
a resumption member function ([[coroutine.handle.resumption]](coroutine.handle.resumption "17.13.4.6Resumption"))
of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4Class template coroutine_­handle"))
that refers to the coroutine[.](#coroutine-9.sentence-1)
The evaluation that invoked a resumption member function is
called the [*resumer*](#def:coroutine,resumer "9.6.4Coroutine definitions[dcl.fct.def.coroutine]")[.](#coroutine-9.sentence-2)
Invoking a resumption member function for a coroutine
that is not suspended results in undefined behavior[.](#coroutine-9.sentence-3)
[10](#coroutine-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7377)
An implementation may need to allocate additional storage for a coroutine[.](#coroutine-10.sentence-1)
This storage is known as the [*coroutine state*](#def:coroutine_state "9.6.4Coroutine definitions[dcl.fct.def.coroutine]") and is obtained by calling
a non-array allocation function ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2Allocation functions"))
as part of the replacement body[.](#coroutine-10.sentence-2)
The allocation function's name is looked up by searching for it in the scope of the promise type[.](#coroutine-10.sentence-3)
- [(10.1)](#coroutine-10.1)
If the search finds any declarations,
overload resolution is performed on a function call created by assembling an
argument list[.](#coroutine-10.1.sentence-1)
The first argument is the amount of space requested, and
is a prvalue of type std::size_t[.](#coroutine-10.1.sentence-2)
The lvalues p1…pn with their original types (including cv-qualifiers)
are the successive arguments[.](#coroutine-10.1.sentence-3)
If no viable function is found ([[over.match.viable]](over.match.viable "12.2.3Viable functions")),
overload resolution is performed again
on a function call created by passing just
the amount of space required as a prvalue of type std::size_t[.](#coroutine-10.1.sentence-4)
- [(10.2)](#coroutine-10.2)
If the search finds no declarations, a search is performed in the global scope[.](#coroutine-10.2.sentence-1)
Overload resolution is performed on a function call created by
passing the amount of space required as a prvalue of type std::size_t[.](#coroutine-10.2.sentence-2)
[11](#coroutine-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7402)
If a search for the name get_return_object_on_allocation_failure in the scope of the promise type ([[class.member.lookup]](class.member.lookup "6.5.2Member name lookup")) finds
any declarations, then the result
of a call to an allocation function used to obtain storage for the coroutine
state is assumed to return nullptr if it fails to obtain storage,
and if a global allocation function is selected,
the ::operator new(size_t, nothrow_t) form is used[.](#coroutine-11.sentence-1)
The allocation function used in this case shall have a non-throwing[*noexcept-specifier*](except.spec#nt:noexcept-specifier "14.5Exception specifications[except.spec]")[.](#coroutine-11.sentence-2)
If the allocation function returns nullptr, the coroutine transfers
control to the caller of the coroutine and the return value is obtained by a
call to T::get_return_object_on_allocation_failure(), where T is the promise type[.](#coroutine-11.sentence-3)
[*Example [2](#coroutine-example-2)*: #include <iostream>#include <coroutine>// ::operator new(size_t, nothrow_t) will be used if allocation is neededstruct generator {struct promise_type; using handle = std::coroutine_handle<promise_type>; struct promise_type {int current_value; static auto get_return_object_on_allocation_failure() { return generator{nullptr}; }auto get_return_object() { return generator{handle::from_promise(*this)}; }auto initial_suspend() { return std::suspend_always{}; }auto final_suspend() noexcept { return std::suspend_always{}; }void unhandled_exception() { std::terminate(); }void return_void() {}auto yield_value(int value) { current_value = value; return std::suspend_always{}; }}; bool move_next() { return coro ? (coro.resume(), !coro.done()) : false; }int current_value() { return coro.promise().current_value; } generator(generator const&) = delete;
generator(generator && rhs) : coro(rhs.coro) { rhs.coro = nullptr; }~generator() { if (coro) coro.destroy(); }private: generator(handle h) : coro(h) {} handle coro;};
generator f() { co_yield 1; co_yield 2; }int main() {auto g = f(); while (g.move_next()) std::cout << g.current_value() << std::endl;} — *end example*]
[12](#coroutine-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7456)
The coroutine state is destroyed when control flows off the end of the
coroutine or the destroy member
function ([[coroutine.handle.resumption]](coroutine.handle.resumption "17.13.4.6Resumption"))
of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4Class template coroutine_­handle"))
that refers to the coroutine
is invoked[.](#coroutine-12.sentence-1)
In the latter case,
control in the coroutine is considered
to be transferred out of the function ([[stmt.dcl]](stmt.dcl "8.10Declaration statement"))[.](#coroutine-12.sentence-2)
The storage for the coroutine state is released by calling a
non-array deallocation function ([[basic.stc.dynamic.deallocation]](basic.stc.dynamic.deallocation "6.8.6.5.3Deallocation functions"))[.](#coroutine-12.sentence-3)
If destroy is called for a coroutine that is not suspended, the
program has undefined behavior[.](#coroutine-12.sentence-4)
[13](#coroutine-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7471)
The deallocation function's name is looked up by searching for it in the scope of the promise type[.](#coroutine-13.sentence-1)
If nothing is found, a search is performed in the
global scope[.](#coroutine-13.sentence-2)
If both a usual deallocation
function with only a pointer parameter and a usual deallocation function with
both a pointer parameter and a size parameter are found, then the selected deallocation
function shall be the one with two parameters[.](#coroutine-13.sentence-3)
Otherwise, the selected
deallocation function shall be the function with one parameter[.](#coroutine-13.sentence-4)
If no usual
deallocation function is found, the program is ill-formed[.](#coroutine-13.sentence-5)
The selected deallocation function shall be called with the address of the
block of storage to be reclaimed as its first argument[.](#coroutine-13.sentence-6)
If a deallocation
function with a parameter of type std::size_t is used, the size of
the block is passed as the corresponding argument[.](#coroutine-13.sentence-7)
[14](#coroutine-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7485)
When a coroutine is invoked,
a copy is created for each coroutine parameter
at the beginning of the replacement body[.](#coroutine-14.sentence-1)
For a parameter
whose original declaration specified the type cv T,
- [(14.1)](#coroutine-14.1)
if T is a reference type,
the copy is a reference of typecv T bound to the same object as a parameter;
- [(14.2)](#coroutine-14.2)
otherwise, the copy is a variable
of type cv T with automatic storage duration that is direct-initialized
from an xvalue of type T referring to the parameter[.](#coroutine-14.sentence-2)
[*Note [3](#coroutine-note-3)*:
An identifier in the [*function-body*](#nt:function-body "9.6.1General[dcl.fct.def.general]") that names one of these parameters
refers to the created copy,
not the original parameter ([[expr.prim.id.unqual]](expr.prim.id.unqual "7.5.5.2Unqualified names"))[.](#coroutine-14.sentence-3)
— *end note*]
The initialization and destruction of each parameter copy occurs in the
context of the called coroutine[.](#coroutine-14.sentence-4)
Initializations of parameter copies are sequenced before the call to the
coroutine promise constructor and indeterminately sequenced with respect to
each other[.](#coroutine-14.sentence-5)
The lifetime of parameter copies ends immediately after the lifetime of the
coroutine promise object ends[.](#coroutine-14.sentence-6)
[*Note [4](#coroutine-note-4)*:
If a coroutine has a parameter passed by reference, resuming the coroutine
after the lifetime of the entity referred to by that parameter has ended is
likely to result in undefined behavior[.](#coroutine-14.sentence-7)
— *end note*]
[15](#coroutine-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7523)
If the evaluation of the expression*promise*.unhandled_exception() exits via an exception,
the coroutine is considered suspended at the final suspend point
and the exception propagates to the caller or resumer[.](#coroutine-15.sentence-1)
[16](#coroutine-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7529)
The expression co_await *promise*.final_suspend() shall not be potentially-throwing ([[except.spec]](except.spec "14.5Exception specifications"))[.](#coroutine-16.sentence-1)
### [9.6.5](#replace) Replaceable function definitions [[dcl.fct.def.replace]](dcl.fct.def.replace)
[1](#replace-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/declarations.tex#L7538)
Certain functions
for which a definition is supplied by the implementation
are [*replaceable*](#def:function,replaceable "9.6.5Replaceable function definitions[dcl.fct.def.replace]")[.](#replace-1.sentence-1)
A C++ program may
provide a definition with the signature of a replaceable function,
called a [*replacement function*](#def:function,replacement "9.6.5Replaceable function definitions[dcl.fct.def.replace]")[.](#replace-1.sentence-2)
The replacement function
is used instead of the default version
supplied by the implementation[.](#replace-1.sentence-3)
Such replacement occurs
prior to program startup ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"), [[basic.start]](basic.start "6.10.3Start and termination"))[.](#replace-1.sentence-4)
A declaration of the replacement function
- [(1.1)](#replace-1.1)
shall not be inline,
- [(1.2)](#replace-1.2)
shall be attached to the global module,
- [(1.3)](#replace-1.3)
shall have C++ language linkage,
- [(1.4)](#replace-1.4)
shall have the same return type as the replaceable function, and
- [(1.5)](#replace-1.5)
if the function is declared in a standard library header,
shall be such that it would be valid as a redeclaration
of the declaration in that header;
no diagnostic is required[.](#replace-1.sentence-5)
[*Note [1](#replace-note-1)*:
The one-definition rule ([[basic.def.odr]](basic.def.odr "6.3One-definition rule"))
applies to the definitions of a replaceable function
provided by the program[.](#replace-1.sentence-6)
The implementation-supplied function definition
is an otherwise-unnamed function with no linkage[.](#replace-1.sentence-7)
— *end note*]