[exec.awaitable] # 33 Execution control library [[exec]](./#exec) ## 33.9 Senders [[exec.snd]](exec.snd#exec.awaitable) ### 33.9.4 Awaitable helpers [exec.awaitable] [1](#1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2304) The sender concepts recognize awaitables as senders[.](#1.sentence-1) For [[exec]](exec "33 Execution control library"), an [*awaitable*](#def:awaitable "33.9.4 Awaitable helpers [exec.awaitable]") is an expression that would be well-formed as the operand of a co_await expression within a given context[.](#1.sentence-2) [2](#2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2310) For a subexpression c, let *GET-AWAITER*(c, p) be expression-equivalent to the series of transformations and conversions applied to c as the operand of an [*await-expression*](expr.await#nt:await-expression "7.6.2.4 Await [expr.await]") in a coroutine, resulting in lvalue e as described by [[expr.await]](expr.await "7.6.2.4 Await"), where p is an lvalue referring to the coroutine's promise, which has type Promise[.](#2.sentence-1) [*Note [1](#note-1)*: This includes the invocation of the promise type's await_transform member if any, the invocation of the operator co_await picked by overload resolution if any, and any necessary implicit conversions and materializations[.](#2.sentence-2) — *end note*] Let *GET-AWAITER*(c) be expression-equivalent to *GET-AWAITER*(c, q) where q is an lvalue of an unspecified empty class type *none-such* that lacks an await_transform member, and where coroutine_handle<*none-such*> behaves ascoroutine_handle[.](#2.sentence-3) [3](#3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2334) Let [*is-awaitable*](#concept:is-awaitable "33.9.4 Awaitable helpers [exec.awaitable]") be the following exposition-only concept:namespace std {templateconcept [*await-suspend-result*](#concept:await-suspend-result "33.9.4 Awaitable helpers [exec.awaitable]") = *see below*; // *exposition only*templateconcept [*is-awaiter*](#concept:is-awaiter "33.9.4 Awaitable helpers [exec.awaitable]") = // *exposition only*requires (A& a, coroutine_handle h) { a.await_ready() ? 1 : 0; { a.await_suspend(h) } -> [*await-suspend-result*](#concept:await-suspend-result "33.9.4 Awaitable helpers [exec.awaitable]"); a.await_resume(); }; templateconcept [*is-awaitable*](#concept:is-awaitable "33.9.4 Awaitable helpers [exec.awaitable]") = // *exposition only*requires (C (*fc)() noexcept, Promise&... p) {{ *GET-AWAITER*(fc(), p...) } -> [*is-awaiter*](#concept:is-awaiter "33.9.4 Awaitable helpers [exec.awaitable]"); };} [*await-suspend-result*](#concept:await-suspend-result "33.9.4 Awaitable helpers [exec.awaitable]") is true if and only if one of the following is true: - [(3.1)](#3.1) T is void, or - [(3.2)](#3.2) T is bool, or - [(3.3)](#3.3) T is a specialization of coroutine_handle[.](#3.sentence-2) [4](#4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2365) For a subexpression c such that decltype((c)) is type C, and an lvalue p of type Promise,*await-result- type* denotes the type decltype(*GET-AWAITER*(c, p).await_resume()) and*await-result-type* denotes the type decltype(*GET-AWAITER*(c).await_resume())[.](#4.sentence-1) [5](#5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2374) Let *with-await-transform* be the exposition-only class template:namespace std::execution {templateconcept [*has-as-awaitable*](#concept:has-as-awaitable "33.9.4 Awaitable helpers [exec.awaitable]") = // *exposition only*requires (T&& t, Promise& p) {{ std::forward(t).as_awaitable(p) } -> [*is-awaitable*](#concept:is-awaitable "33.9.4 Awaitable helpers [exec.awaitable]"); }; templatestruct *with-await-transform* { // *exposition only*template T&& await_transform(T&& value) noexcept {return std::forward(value); }template<[*has-as-awaitable*](#concept:has-as-awaitable "33.9.4 Awaitable helpers [exec.awaitable]") T>auto await_transform(T&& value)noexcept(noexcept(std::forward(value).as_awaitable(declval())))-> decltype(std::forward(value).as_awaitable(declval())) {return std::forward(value).as_awaitable(static_cast(*this)); }};} [6](#6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/exec.tex#L2401) Let *env-promise* be the exposition-only class template:namespace std::execution {templatestruct *env-promise* : *with-await-transform*<*env-promise*> { // *exposition only**unspecified* get_return_object() noexcept; *unspecified* initial_suspend() noexcept; *unspecified* final_suspend() noexcept; void unhandled_exception() noexcept; void return_void() noexcept; coroutine_handle<> unhandled_stopped() noexcept; const Env& get_env() const noexcept; };} [*Note [2](#note-2)*: Specializations of *env-promise* are used only for the purpose of type computation; its members need not be defined[.](#6.sentence-1) — *end note*]