Files
cppdraft_translate/cppdraft/exec/awaitable.md
2025-10-25 03:02:53 +03:00

95 lines
5.3 KiB
Markdown
Raw 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.

[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 "33Execution control library"), an [*awaitable*](#def:awaitable "33.9.4Awaitable 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.4Await[expr.await]") in a coroutine,
resulting in lvalue e as described by [[expr.await]](expr.await "7.6.2.4Await"),
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.4Awaitable helpers[exec.awaitable]") be the following exposition-only concept:namespace std {template<class T>concept [*await-suspend-result*](#concept:await-suspend-result "33.9.4Awaitable helpers[exec.awaitable]") = *see below*; // *exposition only*template<class A, class... Promise>concept [*is-awaiter*](#concept:is-awaiter "33.9.4Awaitable 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.4Awaitable helpers[exec.awaitable]");
a.await_resume(); }; template<class C, class... Promise>concept [*is-awaitable*](#concept:is-awaitable "33.9.4Awaitable helpers[exec.awaitable]") = // *exposition only*requires (C (*fc)() noexcept, Promise&... p) {{ *GET-AWAITER*(fc(), p...) } -> [*is-awaiter*](#concept:is-awaiter "33.9.4Awaitable helpers[exec.awaitable]")<Promise...>; };}
[*await-suspend-result*](#concept:await-suspend-result "33.9.4Awaitable 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.4Awaitable helpers[exec.awaitable]") = // *exposition only*requires (T&& t, Promise& p) {{ std::forward<T>(t).as_awaitable(p) } -> [*is-awaitable*](#concept:is-awaitable "33.9.4Awaitable 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.4Awaitable 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*]