|
| 1 | +# as_awaitable |
| 2 | +* execution[meta header] |
| 3 | +* cpo[meta id-type] |
| 4 | +* std::execution[meta namespace] |
| 5 | +* cpp26[meta cpp] |
| 6 | + |
| 7 | +```cpp |
| 8 | +namespace std::execution { |
| 9 | + struct as_awaitable_t { unspecified }; |
| 10 | + inline constexpr as_awaitable_t as_awaitable{}; |
| 11 | +} |
| 12 | +``` |
| 13 | +* unspecified[italic] |
| 14 | +
|
| 15 | +## 概要 |
| 16 | +`as_awaitable`は、オブジェクトを特定コルーチン内でAwaitableに変換するカスタマイゼーションポイントオブジェクトである。 |
| 17 | +
|
| 18 | +
|
| 19 | +## 効果 |
| 20 | +説明用の式`expr`と左辺値`p`に対して、型`Expr`を`decltype((expr))`、型`Promise`を[`decay_t`](/reference/type_traits/decay.md)`<decltype((p))>`とする。 |
| 21 | +
|
| 22 | +呼び出し式`as_awaitable(expr, p)`は、`expr`と`p`の評価が不定順で順序付けられることを除いて、下記と等価。 |
| 23 | +
|
| 24 | +- 適格であるならば、式`expr.as_awaitable(p)` |
| 25 | + - 適格要件 : 同式の型を`A`としたとき、[`is-awaitable`](../is-awaitable.md)`<A, Promise> == true`であるべき。 |
| 26 | +- そうではなく、説明用の型`U`を`Promise`とは異なりかつ`await_transform`メンバ関数を持たない未規定の型としたとき、[`is-awaitable`](../is-awaitable.md)`<Expr, U> == true`ならば、式`(void(p), expr)` |
| 27 | + - 事前条件 : [`is-awaitable`](../is-awaitable.md)`<Expr, Promise> == true`、かつPromise型`U`のコルーチンにおける式`co_await expr`がPromise型`Promise`のコルーチンにおける同式と等しさを保持すること。 |
| 28 | +- そうではなく、`awaitable-sender<Expr, Promise>`ならば、式`sender-awaitable{expr, p}` |
| 29 | +- そうでなければ、式`(void(p), expr)` |
| 30 | +
|
| 31 | +
|
| 32 | +## 説明専用エンティティ |
| 33 | +### コンセプト`awaitable-sender` |
| 34 | +```cpp |
| 35 | +namespace std::execution { |
| 36 | + template<class Sndr, class Promise> |
| 37 | + concept awaitable-sender = |
| 38 | + single-sender<Sndr, env_of_t<Promise>> && |
| 39 | + sender_to<Sndr, awaitable-receiver> && // see below |
| 40 | + requires (Promise& p) { |
| 41 | + { p.unhandled_stopped() } -> convertible_to<coroutine_handle<>>; |
| 42 | + }; |
| 43 | +} |
| 44 | +``` |
| 45 | +* single-sender[link single-sender.md] |
| 46 | +* sender_to[link sender_to.md] |
| 47 | +* convertible_to[link /reference/concepts/convertible_to.md] |
| 48 | +* coroutine_handle<>[link /reference/coroutine/coroutine_handle.md] |
| 49 | +* see below[italic] |
| 50 | + |
| 51 | +### クラステンプレート`sender-awaitable` |
| 52 | +```cpp |
| 53 | +namespace std::execution { |
| 54 | + template<class Sndr, class Promise> |
| 55 | + class sender-awaitable { |
| 56 | + struct unit {}; // exposition only |
| 57 | + using value-type = // exposition only |
| 58 | + single-sender-value-type<Sndr, env_of_t<Promise>>; |
| 59 | + using result-type = // exposition only |
| 60 | + conditional_t<is_void_v<value-type>, unit, value-type>; |
| 61 | + struct awaitable-receiver; // exposition only |
| 62 | + |
| 63 | + variant<monostate, result-type, exception_ptr> result{}; // exposition only |
| 64 | + connect_result_t<Sndr, awaitable-receiver> state; // exposition only |
| 65 | + |
| 66 | + public: |
| 67 | + sender-awaitable(Sndr&& sndr, Promise& p); |
| 68 | + static constexpr bool await_ready() noexcept { return false; } |
| 69 | + void await_suspend(coroutine_handle<Promise>) noexcept { start(state); } |
| 70 | + value-type await_resume(); |
| 71 | + }; |
| 72 | +} |
| 73 | +``` |
| 74 | +* single-sender-value-type[link single-sender-value-type.md] |
| 75 | +* env_of_t[link env_of_t.md] |
| 76 | +* connect_result_t[link connect_result_t.md] |
| 77 | +* start[link start.md] |
| 78 | +* conditional_t[link /reference/type_traits/conditional.md] |
| 79 | +* is_void_v[link /reference/type_traits/is_void.md] |
| 80 | +* variant[link /reference/variant/variant.md] |
| 81 | +* monostate[link /reference/variant/monostate.md] |
| 82 | +* exception_ptr[link /reference/exception/exception_ptr.md] |
| 83 | +* coroutine_handle[link /reference/coroutine/coroutine_handle.md] |
| 84 | +
|
| 85 | +### クラステンプレート`awaitable-receiver` |
| 86 | +説明専用のクラステンプレート`sender-awaitable<Sndr, Promise>::awaitable-receiver`は下記の通り定義される。 |
| 87 | +
|
| 88 | +```cpp |
| 89 | +struct awaitable-receiver { |
| 90 | + using receiver_concept = receiver_t; |
| 91 | + variant<monostate, result-type, exception_ptr>* result-ptr; // exposition only |
| 92 | + coroutine_handle<Promise> continuation; // exposition only |
| 93 | + // see below |
| 94 | +}; |
| 95 | +``` |
| 96 | +* receiver_t[link receiver.md] |
| 97 | +* variant[link /reference/variant/variant.md] |
| 98 | +* monostate[link /reference/variant/monostate.md] |
| 99 | +* exception_ptr[link /reference/exception/exception_ptr.md] |
| 100 | +* coroutine_handle[link /reference/coroutine/coroutine_handle.md] |
| 101 | +* see below[italic] |
| 102 | + |
| 103 | +説明用の式`rcvr`を`awaitable-reciever`型の右辺値、`crcvr`を`rcvr`をconst参照する左辺値、`vs`を式パック、`err`を`Err`型の式とする。このとき |
| 104 | + |
| 105 | +- [`constructible_from`](/reference/concepts/constructible_from.md)`<result-type, decltype((vs))...>`を満たすとき、式`set_value(rcvr, vs...)`は下記と等価。そうでなければ、式`set_value(rcvr, vs...)`は不適格となる。 |
| 106 | + |
| 107 | + ```cpp |
| 108 | + try { |
| 109 | + rcvr.result-ptr->template emplace<1>(vs...); |
| 110 | + } catch(...) { |
| 111 | + rcvr.result-ptr->template emplace<2>(current_exception()); |
| 112 | + } |
| 113 | + rcvr.continuation.resume(); |
| 114 | + ``` |
| 115 | + * template emplace[link /reference/variant/variant/emplace.md] |
| 116 | + * current_exception()[link /reference/exception/current_exception.md] |
| 117 | + * resume()[link /reference/coroutine/coroutine_handle/resume.md] |
| 118 | + |
| 119 | +- 式`set_error(rcvr, err)`は下記と等価。 |
| 120 | + |
| 121 | + ```cpp |
| 122 | + rcvr.result-ptr->template emplace<2>(AS-EXCEPT-PTR(err)); |
| 123 | + rcvr.continuation.resume(); |
| 124 | + ``` |
| 125 | + * template emplace[link /reference/variant/variant/emplace.md] |
| 126 | + * resume()[link /reference/coroutine/coroutine_handle/resume.md] |
| 127 | + |
| 128 | +- 式`set_stopped(rcvr)`は下記と等価。 |
| 129 | + |
| 130 | + ```cpp |
| 131 | + static_cast<coroutine_handle<>>(rcvr.continuation.promise().unhandled_stopped()).resume(); |
| 132 | + ``` |
| 133 | + * coroutine_handle<>[link /reference/coroutine/coroutine_handle.md] |
| 134 | + * promise()[link /reference/coroutine/coroutine_handle/promise.md] |
| 135 | + * resume()[link /reference/coroutine/coroutine_handle/resume.md] |
| 136 | + |
| 137 | +- [`forwarding-query`](../forwarding-query.md)を満たす型の式`tag`とパック式`as`に対して、[`get_env`](get_env.md)`(crcvr).query(tag, as...)`は下記と等価。 |
| 138 | + |
| 139 | + ```cpp |
| 140 | + tag(get_env(as_const(crcvr.continuation.promise())), as...) |
| 141 | + ``` |
| 142 | + * get_env[link get_env.md] |
| 143 | + * as_const[link /reference/utility/as_const.md] |
| 144 | + * promise()[link /reference/coroutine/coroutine_handle/promise.md] |
| 145 | + |
| 146 | +```cpp |
| 147 | +sender-awaitable(Sndr&& sndr, Promise& p); |
| 148 | +``` |
| 149 | + |
| 150 | +- 効果 : `state`を下記で初期化する。 |
| 151 | + |
| 152 | + ```cpp |
| 153 | + connect(std::forward<Sndr>(sndr), |
| 154 | + awaitable-receiver{addressof(result), coroutine_handle<Promise>::from_promise(p)}) |
| 155 | + ``` |
| 156 | + * connect[link connect.md] |
| 157 | + * coroutine_handle[link /reference/coroutine/coroutine_handle.md] |
| 158 | + * from_promise[link /reference/coroutine/coroutine_handle/from_promise.md] |
| 159 | + |
| 160 | +```cpp |
| 161 | +value-type await_resume(); |
| 162 | +``` |
| 163 | + |
| 164 | +- 効果 : 下記と等価。 |
| 165 | + |
| 166 | + ```cpp |
| 167 | + if (result.index() == 2) |
| 168 | + rethrow_exception(get<2>(result)); |
| 169 | + if constexpr (!is_void_v<value-type>) |
| 170 | + return std::forward<value-type>(get<1>(result)); |
| 171 | + ``` |
| 172 | + * index()[link /reference/variant/variant/index.md] |
| 173 | + * get[link /reference/variant/variant/get.md] |
| 174 | + * rethrow_exception[link /reference/exception/rethrow_exception.md] |
| 175 | + * is_void_v[link /reference/type_traits/is_void.md] |
| 176 | + |
| 177 | + |
| 178 | +## カスタマイゼーションポイント |
| 179 | +`expr`に対して、適格であるならば式`expr.as_awaitable(p)`が呼び出される。 |
| 180 | + |
| 181 | + |
| 182 | +## バージョン |
| 183 | +### 言語 |
| 184 | +- C++26 |
| 185 | + |
| 186 | +### 処理系 |
| 187 | +- [Clang](/implementation.md#clang): ?? |
| 188 | +- [GCC](/implementation.md#gcc): ?? |
| 189 | +- [ICC](/implementation.md#icc): ?? |
| 190 | +- [Visual C++](/implementation.md#visual_cpp): ?? |
| 191 | + |
| 192 | + |
| 193 | +## 関連項目 |
| 194 | +- [`execution::with_awaitable_senders`](with_awaitable_senders.md) |
| 195 | +- [C++20 コルーチン](/lang/cpp20/coroutines.md) |
| 196 | + |
| 197 | + |
| 198 | +## 参照 |
| 199 | +- [P2300R10 `std::execution`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2300r10.html) |
0 commit comments