[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<void>[.](#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 {template<class T>concept [*await-suspend-result*](#concept:await-suspend-result "33.9.4 Awaitable helpers [exec.awaitable]") = *see below*; // *exposition only*template<class A, class... Promise>concept [*is-awaiter*](#concept:is-awaiter "33.9.4 Awaitable helpers [exec.awaitable]") = // *exposition only*requires (A& a, coroutine_handle<Promise...> 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(); }; template<class C, class... Promise>concept [*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]")<Promise...>; };}

[*await-suspend-result*](#concept:await-suspend-result "33.9.4 Awaitable helpers [exec.awaitable]")<T> 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*<C, Promise> denotes
the type decltype(*GET-AWAITER*(c, p).await_resume()) and*await-result-type*<C> 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 {template<class T, class Promise>concept [*has-as-awaitable*](#concept:has-as-awaitable "33.9.4 Awaitable helpers [exec.awaitable]") = // *exposition only*requires (T&& t, Promise& p) {{ std::forward<T>(t).as_awaitable(p) } -> [*is-awaitable*](#concept:is-awaitable "33.9.4 Awaitable helpers [exec.awaitable]")<Promise&>; }; template<class Derived>struct *with-await-transform* { // *exposition only*template<class T> T&& await_transform(T&& value) noexcept {return std::forward<T>(value); }template<[*has-as-awaitable*](#concept:has-as-awaitable "33.9.4 Awaitable helpers [exec.awaitable]")<Derived> T>auto await_transform(T&& value)noexcept(noexcept(std::forward<T>(value).as_awaitable(declval<Derived&>())))-> decltype(std::forward<T>(value).as_awaitable(declval<Derived&>())) {return std::forward<T>(value).as_awaitable(static_cast<Derived&>(*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 {template<class Env>struct *env-promise* : *with-await-transform*<*env-promise*<Env>> { // *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*]
