[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.1 General [dcl.fct.def.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 [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") [*virt-specifier-seq*](class.mem.general#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 [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.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 [*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 [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]") [function-body:](#nt:function-body "9.6.1 General [dcl.fct.def.general]") [*ctor-initializer*](class.base.init#nt:ctor-initializer "11.9.3 Initializing bases and members [class.base.init]")opt [*compound-statement*](stmt.block#nt:compound-statement "8.4 Compound statement or block [stmt.block]") [*function-try-block*](except.pre#nt:function-try-block "14.1 Preamble [except.pre]") = default ; [*deleted-function-body*](#nt:deleted-function-body "9.6.1 General [dcl.fct.def.general]") [deleted-function-body:](#nt:deleted-function-body "9.6.1 General [dcl.fct.def.general]") = delete ; = delete ( [*unevaluated-string*](lex.string.uneval#nt:unevaluated-string "5.13.6 Unevaluated 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.1 General [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.3 Initializing bases and members [class.base.init]") ([[class.base.init]](class.base.init "11.9.3 Initializing bases and members"))[.](#general-1.sentence-2) The optional [*attribute-specifier-seq*](dcl.attr.grammar#nt:attribute-specifier-seq "9.13.1 Attribute syntax and semantics [dcl.attr.grammar]") in a [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") appertains to the function[.](#general-1.sentence-3) A [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") with a [*virt-specifier-seq*](class.mem.general#nt:virt-specifier-seq "11.4.1 General [class.mem.general]") shall be a [*member-declaration*](class.mem.general#nt:member-declaration "11.4.1 General [class.mem.general]") ([[class.mem]](class.mem "11.4 Class members"))[.](#general-1.sentence-4) A [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") with a [*requires-clause*](temp.pre#nt:requires-clause "13.1 Preamble [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.1 General [dcl.fct.def.general]"), either void [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") ; or [*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]") ; shall be a well-formed function declaration as described in [[dcl.fct]](dcl.fct "9.3.4.6 Functions")[.](#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.3 Deleted 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.1 General [dcl.spec.general]");max(inta,intb,intc) is the[*declarator*](dcl.decl.general#nt:declarator "9.3.1 General [dcl.decl.general]");{ /* ... */ } is the[*function-body*](#nt:function-body "9.6.1 General [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.3 Initializing bases and members [class.base.init]") is used only in a constructor; see [[class.ctor]](class.ctor "11.4.5 Constructors") and [[class.init]](class.init "11.9 Initialization")[.](#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.1 General [dcl.decl.general]") affects the type of this in the body of a member function; see [[expr.prim.this]](expr.prim.this "7.5.3 This")[.](#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.1 General [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.11 Identifiers"))[.](#footnote-81.sentence-1) If a predefined variable is not odr-used ([[basic.def.odr]](basic.def.odr#term.odr.use "6.3 One-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.1 General [dcl.fct.def.general]") is of the form= default ; is called an [*explicitly-defaulted*](#def:definition,function,explicitly-defaulted "9.6.2 Explicitly-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.4 Special member functions")) or a comparison operator function ([[over.binary]](over.binary "12.4.3 Binary operators"), [[class.compare.default]](class.compare.default "11.10.1 Defaulted comparison operator functions")), and - [(1.2)](#default-1.2) not have default arguments ([[dcl.fct.default]](dcl.fct.default "9.3.4.7 Default 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.1 General [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.8 The inline specifier")), and is implicitly constexpr ([[dcl.constexpr]](dcl.constexpr "9.2.6 The 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(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.2 Explicitly-defaulted functions [dcl.fct.def.default]") functions, and the implementation shall provide implicit definitions for them ([[class.ctor]](class.ctor "11.4.5 Constructors"), [[class.dtor]](class.dtor "11.4.7 Destructors"), [[class.copy.ctor]](class.copy.ctor "11.4.5.3 Copy/move constructors"), [[class.copy.assign]](class.copy.assign "11.4.6 Copy/move assignment operator")) as described below, including possibly defining them as deleted[.](#default-5.sentence-1) A defaulted prospective destructor ([[class.dtor]](class.dtor "11.4.7 Destructors")) 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.4 Special member functions")) is defined as deleted[.](#default-5.sentence-3) A function is[*user-provided*](#def:user-provided "9.6.2 Explicitly-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.3 One-definition rule")) or needed for constant evaluation ([[expr.const]](expr.const "7.7 Constant 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.3 Deleted definitions [dcl.fct.def.delete]") of a function is a function definition whose [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]") is a [*deleted-function-body*](#nt:deleted-function-body "9.6.1 General [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.3 Deleted 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.10 The reflection operator [expr.reflect]") ([[expr.reflect]](expr.reflect "7.6.2.10 The 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.6 Unevaluated 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.3 One-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.6 Unevaluated 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 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.8 New [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.8 The inline specifier"))[.](#delete-4.sentence-1) [*Note [2](#delete-note-2)*: The one-definition rule ([[basic.def.odr]](basic.def.odr "6.3 One-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.5 Dynamic 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.4 Coroutine definitions [dcl.fct.def.coroutine]") if its [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]") encloses a[*coroutine-return-statement*](stmt.return.coroutine#nt:coroutine-return-statement "8.8.5 The co_­return statement [stmt.return.coroutine]") ([[stmt.return.coroutine]](stmt.return.coroutine "8.8.5 The co_­return statement")), an [*await-expression*](expr.await#nt:await-expression "7.6.2.4 Await [expr.await]") ([[expr.await]](expr.await "7.6.2.4 Await")), or a [*yield-expression*](expr.yield#nt:yield-expression "7.6.17 Yielding a value [expr.yield]") ([[expr.yield]](expr.yield "7.6.17 Yielding a value"))[.](#coroutine-1.sentence-1) The [*parameter-declaration-clause*](dcl.fct#nt:parameter-declaration-clause "9.3.4.6 Functions [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.6 Functions [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 f(); task g1() {int i = co_await f(); std::cout << "f() => " << i << std::endl;}template task g2(Args&&...) { // OK, ellipsis is a pack expansionint i = co_await f(); std::cout << "f() => " << i << std::endl;} task 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.4 Coroutine definitions [dcl.fct.def.coroutine]") of a coroutine isstd​::​coroutine_traits​::​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.6 Functions")) 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.6 Functions [dcl.fct]")*s* in the declarator of its [*function-definition*](#nt:function-definition "9.6.1 General [dcl.fct.def.general]") were removed and its [*function-body*](#nt:function-body "9.6.1 General [dcl.fct.def.general]") were replaced by the following [*replacement body*](#def:body,replacement "9.6.4 Coroutine definitions [dcl.fct.def.coroutine]"): { *promise-type* *promise* *promise-constructor-arguments* ; try { co_await *promise*.initial_suspend() ; [*function-body*](#nt:function-body "9.6.1 General [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.4 Await [expr.await]") containing the call to initial_suspend is the [*initial await expression*](#def:await_expression,initial "9.6.4 Coroutine definitions [dcl.fct.def.coroutine]"), and - [(5.2)](#coroutine-5.2) the [*await-expression*](expr.await#nt:await-expression "7.6.2.4 Await [expr.await]") containing the call to final_suspend is the [*final await expression*](#def:await_expression,final "9.6.4 Coroutine 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.4 Await")) 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.4 Coroutine 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.5 The 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.3 Viable 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.4 Coroutine 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.4 Coroutine 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.1 General"))[.](#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.5 The 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.6 Resumption")) of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4 Class 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.4 Coroutine 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.4 Coroutine 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.2 Allocation 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.3 Viable 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.2 Member 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.5 Exception 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 #include // ​::​operator new(size_t, nothrow_t) will be used if allocation is neededstruct generator {struct promise_type; using handle = std::coroutine_handle; 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.6 Resumption")) of a coroutine handle ([[coroutine.handle]](coroutine.handle "17.13.4 Class 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.10 Declaration 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.3 Deallocation 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.1 General [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.2 Unqualified 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.5 Exception 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.5 Replaceable 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.5 Replaceable 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.3 One-definition rule"), [[basic.start]](basic.start "6.10.3 Start 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.3 One-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*]