namespace std::execution {
struct as_awaitable_t { unspecified };
inline constexpr as_awaitable_t as_awaitable{};
}
概要
as_awaitable
は、オブジェクトを特定のコルーチン内でAwaitableに変換するカスタマイゼーションポイントオブジェクトである。
Promise型p
をもつコルーチンにおいて、Await式co_await as_awaitable(expr, p)
は下記のように動作する。
- 式
expr.as_awaitable(p)
が有効ならば、同式が返すAwaitableオブジェクトに対してAwait式を実行する。 expr
が単一の値を送信するSenderであり、Promise型が停止完了ハンドラを定義するならば、下記動作を行う。- Senderを接続(connect)し、結果Operation StateをAwaitableオブジェクトに格納する。
- コルーチンを中断し、Operation Stateを開始(start)する。
- クエリオブジェクトによるReceiver環境への問い合わせは、Promise型に関連付けられた環境(
get_env
)へと転送される。 - Senderが値完了した場合、送信値をAwait式の結果としてコルーチンを再開する。
- Senderがエラー完了した場合、エラー値を例外としてコルーチンから再スローする。
- Senderが停止完了した場合、停止完了ハンドラ(
unhandled_stopped
)が返す別のコルーチンを再開させる。
- そうでなければ、式
expr
に対してAwait式を実行する。
効果
説明用の式expr
と左辺値p
に対して、型Expr
をdecltype((expr))
、型Promise
をdecay_t<decltype((p))>
とする。
呼び出し式as_awaitable(expr, p)
は、expr
とp
の評価が不定順で順序付けられることを除いて、下記と等価。
- 適格であるならば、式
expr.as_awaitable(p)
- 適格要件 : 同式の型を
A
としたとき、is-awaitable<A, Promise> == true
であるべき。
- 適格要件 : 同式の型を
- そうではなく、説明用の型
U
をPromise
とは異なりかつawait_transform
メンバ関数を持たない未規定の型としたとき、is-awaitable<Expr, U> == true
ならば、式(void(p), expr)
- 事前条件 :
is-awaitable<Expr, Promise> == true
、かつPromise型U
のコルーチンにおける式co_await expr
がPromise型Promise
のコルーチンにおける同式と等しさを保持すること。
- 事前条件 :
- そうではなく、
awaitable-sender<Expr, Promise>
ならば、式sender-awaitable{expr, p}
- そうでなければ、式
(void(p), expr)
説明専用エンティティ
コンセプトawaitable-sender
namespace std::execution {
template<class Sndr, class Promise>
concept awaitable-sender =
single-sender<Sndr, env_of_t<Promise>> &&
sender_to<Sndr, awaitable-receiver> && // see below
requires (Promise& p) {
{ p.unhandled_stopped() } -> convertible_to<coroutine_handle<>>;
};
}
クラステンプレートsender-awaitable
namespace std::execution {
template<class Sndr, class Promise>
class sender-awaitable {
struct unit {}; // exposition only
using value-type = // exposition only
single-sender-value-type<Sndr, env_of_t<Promise>>;
using result-type = // exposition only
conditional_t<is_void_v<value-type>, unit, value-type>;
struct awaitable-receiver; // exposition only
variant<monostate, result-type, exception_ptr> result{}; // exposition only
connect_result_t<Sndr, awaitable-receiver> state; // exposition only
public:
sender-awaitable(Sndr&& sndr, Promise& p);
static constexpr bool await_ready() noexcept { return false; }
void await_suspend(coroutine_handle<Promise>) noexcept { start(state); }
value-type await_resume();
};
}
式AS-EXCEPT-PTR
説明用の式err
に対してdecltype((err))
を型Err
としたとき、式AS-EXCEPT-PTR(err)
を下記の通り定義する。
decay_t<Err>
がexception_ptr
型と等しければ、err
となる。このとき、事前条件として!err == false
であること。- そうではなく、
decay_t<Err>
がerror_code
型と等しければ、make_exception_ptr(system_error(err))
となる。 - そうでなければ、
make_exception_ptr(err)
となる。
クラステンプレートawaitable-receiver
説明専用のクラステンプレートsender-awaitable<Sndr, Promise>::awaitable-receiver
は下記の通り定義される。
struct awaitable-receiver {
using receiver_concept = receiver_t;
variant<monostate, result-type, exception_ptr>* result-ptr; // exposition only
coroutine_handle<Promise> continuation; // exposition only
// see below
};
説明用の式rcvr
をawaitable-reciever
型の右辺値、crcvr
をrcvr
をconst参照する左辺値、vs
を式パック、err
をErr
型の式とする。このとき
-
constructible_from<result-type, decltype((vs))...>
を満たすとき、式set_value(rcvr, vs...)
は下記と等価。そうでなければ、式set_value(rcvr, vs...)
は不適格となる。try { rcvr.result-ptr->template emplace<1>(vs...); } catch(...) { rcvr.result-ptr->template emplace<2>(current_exception()); } rcvr.continuation.resume();
-
式
set_error(rcvr, err)
は下記と等価。rcvr.result-ptr->template emplace<2>(AS-EXCEPT-PTR(err)); rcvr.continuation.resume();
-
式
set_stopped(rcvr)
は下記と等価。static_cast<coroutine_handle<>>(rcvr.continuation.promise().unhandled_stopped()).resume();
-
forwarding-query
を満たす型の式tag
とパック式as
に対して、式get_env(crcvr).query(tag, as...)
は下記と等価。
sender-awaitable(Sndr&& sndr, Promise& p);
-
効果 :
state
を下記で初期化する。connect(std::forward<Sndr>(sndr), awaitable-receiver{addressof(result), coroutine_handle<Promise>::from_promise(p)})
value-type await_resume();
-
効果 : 下記と等価。
if (result.index() == 2) rethrow_exception(get<2>(result)); if constexpr (!is_void_v<value-type>) return std::forward<value-type>(get<1>(result));
カスタマイゼーションポイント
expr
に対して、適格であるならば式expr.as_awaitable(p)
が呼び出される。
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??