namespace std::execution {
struct stopped_as_error_t { unspecified };
inline constexpr stopped_as_error_t stopped_as_error{};
}
概要
stopped_as_error
は、入力Senderの停止完了をカスタムエラー型のエラー完了にマップするSenderアダプタである。
stopped_as_error
はパイプ可能Senderアダプタオブジェクトであり、パイプライン記法をサポートする。
効果
説明用の式sndr
とerr
に対して、型Sndr
をdecltype((sndr))
、型Err
をdecltype((err))
とする。Sndr
がsender
を満たさない、もしくはErr
がmoveable-value
を満たさないとき、呼び出し式stopped_as_error(sndr, err)
は不適格となる。
そうでなければ、呼び出し式stopped_as_error(sndr, err)
はsndr
が1回だけ評価されることを除いて、下記と等価。
transform_sender(get-domain-early(sndr), make-sender(stopped_as_error, err, sndr))
Senderアルゴリズムタグ stopped_as_error
説明用の式sndr
とenv
に対して、型Sndr
をdecltype((sndr))
、型Env
をdecltype((env))
とする。sender-for<Sndr, stopped_as_error_t> == false
のとき、式stopped_as_error.transform_sender(sndr, env)
は不適格となる。
そうでなければ、式stopped_as_error.transform_sender(sndr, env)
は下記と等価。
auto&& [_, err, child] = sndr;
using E = decltype(auto(err));
return let_stopped(
std::forward_like<Sndr>(child),
[err = std::forward_like<Sndr>(err)]() mutable noexcept(is_nothrow_move_constructible_v<E>) {
return just_error(std::move(err));
});
カスタマイゼーションポイント
Senderアルゴリズム構築時に、Sendersndr
に関連付けられた実行ドメインに対してexecution::transform_sender
経由でSender変換が行われる。
デフォルト実行ドメインでは無変換。
Receiverとの接続(connect)時に、関連付けられた実行ドメインに対してexecution::transform_sender
経由でSender変換が行われる。
デフォルト実行ドメインではstopped_as_error.transform_sender(sndr, env)
が呼ばれ、前述仕様通りのSenderへと変換される。
例
#include <cassert>
#include <execution>
namespace ex = std::execution;
// MySenderは下記いずれかの完了操作を行う
// 値完了 set_value(int)
// 停止完了 set_stopped()
struct MySender {
using sender_concept = ex::sender_t;
using completion_signatures = ex::completion_signatures<
ex::set_value_t(int),
ex::set_stopped_t()
>;
template <typename Rcvr>
struct state {
using operation_state_concept = ex::operation_state_t;
state(Rcvr rcvr, int val)
: rcvr_{std::move(rcvr)}, val_{val} {}
void start() noexcept {
if (0 < val_) {
ex::set_value(std::move(rcvr_), val_);
} else {
ex::set_stopped(std::move(rcvr_));
}
}
Rcvr rcvr_;
int val_;
};
template <typename Rcvr>
auto connect(Rcvr rcvr) noexcept {
return state{std::move(rcvr), val_};
}
int val_;
};
int main()
{
{ // 関数呼び出し
ex::sender auto snd0 = MySender{-1};
ex::sender auto snd1 = ex::stopped_as_error(snd0, MyStoppedError{});
try {
auto [result] = std::this_thread::sync_wait(snd1).value();
std::println("(int) {}", result);
} catch (MyStoppedError) {
std::println("stopped");
}
}
{ // パイプライン記法
ex::sender auto sndr =
MySender{-1}
| ex::stopped_as_error(MyStoppedError{});
try {
auto [result] = std::this_thread::sync_wait(sndr).value();
std::println("(int) {}", result);
} catch (MyStoppedError) {
std::println("stopped");
}
}
}
出力
stopped
stopped
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??