namespace std::execution {
struct stopped_as_optional_t { unspecified };
inline constexpr stopped_as_optional_t stopped_as_optional{};
}
概要
stopped_as_optional
は、入力Senderの停止完了を空のoptional
による値完了にマップするSenderアダプタである。入力Senderの値完了操作もoptional
へと変換される。
stopped_as_optional
はパイプ可能Senderアダプタオブジェクトであり、パイプライン記法をサポートする。
効果
説明用の式sndr
に対して、型Sndr
をdecltype((sndr))
とする。呼び出し式stopped_as_optional(sndr)
はsndr
が1回だけ評価されることを除いて、下記と等価。
transform_sender(get-domain-early(sndr), make-sender(stopped_as_optional, {}, sndr))
Senderアルゴリズムタグ stopped_as_optional
説明用の式sndr
とenv
に対して、型Sndr
をdecltype((sndr))
、型Env
をdecltype((env))
とする。sender-for<Sndr, stopped_as_optional_t> == false
、もしくはsingle-sender-value-type<Sndr, Env>
が不適格またはvoid
のとき、式stopped_as_optional.transform_sender(sndr, env)
は不適格となる。
そうでなければ、式stopped_as_optional.transform_sender(sndr, env)
は下記と等価。
auto&& [_, _, child] = sndr;
using V = single-sender-value-type<Sndr, Env>;
return let_stopped(
then(std::forward_like<Sndr>(child),
[]<class... Ts>(Ts&&... ts) noexcept(is_nothrow_constructible_v<V, Ts...>) {
return optional<V>(in_place, std::forward<Ts>(ts)...);
}),
[]() noexcept { return just(optional<V>()); });
カスタマイゼーションポイント
Senderアルゴリズム構築時に、Sendersndr
に関連付けられた実行ドメインに対してexecution::transform_sender
経由でSender変換が行われる。
デフォルト実行ドメインでは無変換。
Receiverとの接続(connect)時に、関連付けられた実行ドメインに対してexecution::transform_sender
経由でSender変換が行われる。
デフォルト実行ドメインではstopped_as_optional.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_optional(snd0);
auto [result] = std::this_thread::sync_wait(snd1).value();
if (result) {
std::println("(int) {}", *result);
} else {
std::println("stopped");
}
}
{ // パイプライン記法
ex::sender auto sndr = MySender{-1} | ex::stopped_as_optional();
auto [result] = std::this_thread::sync_wait(sndr).value();
if (result) {
std::println("(int) {}", *result);
} else {
std::println("stopped");
}
}
}
出力
stopped
stopped
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??