tmp/tmp7hgrto1a/{from.md → to.md}
RENAMED
|
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
### Awaitable helpers <a id="exec.awaitable">[[exec.awaitable]]</a>
|
| 2 |
+
|
| 3 |
+
The sender concepts recognize awaitables as senders. For [[exec]], an
|
| 4 |
+
*awaitable* is an expression that would be well-formed as the operand of
|
| 5 |
+
a `co_await` expression within a given context.
|
| 6 |
+
|
| 7 |
+
For a subexpression `c`, let `GET-AWAITER(c, p)` be
|
| 8 |
+
expression-equivalent to the series of transformations and conversions
|
| 9 |
+
applied to `c` as the operand of an *await-expression* in a coroutine,
|
| 10 |
+
resulting in lvalue `e` as described by [[expr.await]], where `p` is an
|
| 11 |
+
lvalue referring to the coroutine’s promise, which has type `Promise`.
|
| 12 |
+
|
| 13 |
+
[*Note 1*: This includes the invocation of the promise type’s
|
| 14 |
+
`await_transform` member if any, the invocation of the
|
| 15 |
+
`operator co_await` picked by overload resolution if any, and any
|
| 16 |
+
necessary implicit conversions and materializations. — *end note*]
|
| 17 |
+
|
| 18 |
+
Let `GET-AWAITER(c)` be expression-equivalent to `GET-AWAITER(c, q)`
|
| 19 |
+
where `q` is an lvalue of an unspecified empty class type `none-such`
|
| 20 |
+
that lacks an `await_transform` member, and where
|
| 21 |
+
`coroutine_handle<none-such>` behaves as `coroutine_handle<void>`.
|
| 22 |
+
|
| 23 |
+
Let `is-awaitable` be the following exposition-only concept:
|
| 24 |
+
|
| 25 |
+
``` cpp
|
| 26 |
+
namespace std {
|
| 27 |
+
template<class T>
|
| 28 |
+
concept await-suspend-result = see below; // exposition only
|
| 29 |
+
|
| 30 |
+
template<class A, class... Promise>
|
| 31 |
+
concept is-awaiter = // exposition only
|
| 32 |
+
requires (A& a, coroutine_handle<Promise...> h) {
|
| 33 |
+
a.await_ready() ? 1 : 0;
|
| 34 |
+
{ a.await_suspend(h) } -> await-suspend-result;
|
| 35 |
+
a.await_resume();
|
| 36 |
+
};
|
| 37 |
+
|
| 38 |
+
template<class C, class... Promise>
|
| 39 |
+
concept is-awaitable = // exposition only
|
| 40 |
+
requires (C (*fc)() noexcept, Promise&... p) {
|
| 41 |
+
{ GET-AWAITER(fc(), p...) } -> is-awaiter<Promise...>;
|
| 42 |
+
};
|
| 43 |
+
}
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
`\defexposconcept{await-suspend-result}<T>` is `true` if and only if one
|
| 47 |
+
of the following is `true`:
|
| 48 |
+
|
| 49 |
+
- `T` is `void`, or
|
| 50 |
+
- `T` is `bool`, or
|
| 51 |
+
- `T` is a specialization of `coroutine_handle`.
|
| 52 |
+
|
| 53 |
+
For a subexpression `c` such that `decltype((c))` is type `C`, and an
|
| 54 |
+
lvalue `p` of type `Promise`, `await-result- type<C, Promise>` denotes
|
| 55 |
+
the type `decltype(GET-AWAITER(c, p).await_resume())` and
|
| 56 |
+
`await-result-type<C>` denotes the type
|
| 57 |
+
`decltype(GET-AWAITER(c).await_resume())`.
|
| 58 |
+
|
| 59 |
+
Let *`with-await-transform`* be the exposition-only class template:
|
| 60 |
+
|
| 61 |
+
``` cpp
|
| 62 |
+
namespace std::execution {
|
| 63 |
+
template<class T, class Promise>
|
| 64 |
+
concept has-as-awaitable = // exposition only
|
| 65 |
+
requires (T&& t, Promise& p) {
|
| 66 |
+
{ std::forward<T>(t).as_awaitable(p) } -> is-awaitable<Promise&>;
|
| 67 |
+
};
|
| 68 |
+
|
| 69 |
+
template<class Derived>
|
| 70 |
+
struct with-await-transform { // exposition only
|
| 71 |
+
template<class T>
|
| 72 |
+
T&& await_transform(T&& value) noexcept {
|
| 73 |
+
return std::forward<T>(value);
|
| 74 |
+
}
|
| 75 |
+
|
| 76 |
+
template<has-as-awaitable<Derived> T>
|
| 77 |
+
auto await_transform(T&& value)
|
| 78 |
+
noexcept(noexcept(std::forward<T>(value).as_awaitable(declval<Derived&>())))
|
| 79 |
+
-> decltype(std::forward<T>(value).as_awaitable(declval<Derived&>())) {
|
| 80 |
+
return std::forward<T>(value).as_awaitable(static_cast<Derived&>(*this));
|
| 81 |
+
}
|
| 82 |
+
};
|
| 83 |
+
}
|
| 84 |
+
```
|
| 85 |
+
|
| 86 |
+
Let *`env-promise`* be the exposition-only class template:
|
| 87 |
+
|
| 88 |
+
``` cpp
|
| 89 |
+
namespace std::execution {
|
| 90 |
+
template<class Env>
|
| 91 |
+
struct env-promise : with-await-transform<env-promise<Env>> { // exposition only
|
| 92 |
+
unspecified get_return_object() noexcept;
|
| 93 |
+
unspecified initial_suspend() noexcept;
|
| 94 |
+
unspecified final_suspend() noexcept;
|
| 95 |
+
void unhandled_exception() noexcept;
|
| 96 |
+
void return_void() noexcept;
|
| 97 |
+
coroutine_handle<> unhandled_stopped() noexcept;
|
| 98 |
+
|
| 99 |
+
const Env& get_env() const noexcept;
|
| 100 |
+
};
|
| 101 |
+
}
|
| 102 |
+
```
|
| 103 |
+
|
| 104 |
+
[*Note 2*: Specializations of *`env-promise`* are used only for the
|
| 105 |
+
purpose of type computation; its members need not be
|
| 106 |
+
defined. — *end note*]
|
| 107 |
+
|