95 lines
5.3 KiB
Markdown
95 lines
5.3 KiB
Markdown
[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*]
|