namespace std::execution {
struct when_all_with_variant_t { unspecified };
inline constexpr when_all_with_variant_t when_all_with_variant{};
}
概要
when_all_with_variant
は、複数の入力Senderが全て完了するまで待機するSenderアダプタである。
when_all_with_variant
は入力Senderが複数の値完了シグネチャを持つケースに対応する。
全入力Senderの値完了シグネチャが1個だけの場合はwhen_all
アルゴリズムを利用する。
- 入力Sender全てが値完了のとき、全ての値完了結果を
variant
のtuple
に結合して値完了操作を行う。 - いずれかがエラー完了のとき、同エラー値をもってエラー完了操作を行う。このとき停止要求が作成される。
- いずれかが停止完了のとき、停止完了操作を行う。このとき停止要求が作成される。
効果
説明用のパックsndrs
に対してパックSndrs
をdecltype((sndrs))...
としたとき、型CD
をcommon_type_t<decltype(get-domain-early(sndrs))...>
とする。
下記いずれかがtrue
となるとき、呼び出し式when_all_with_variant(sndrs...)
は不適格となる。
そうでなければ、呼び出し式when_all_with_variant(sndrs...)
は下記と等価。
transform_sender(CD(), make-sender(when_all_with_variant, {}, sndrs...))
Senderアルゴリズムタグ when_all_with_variant
説明用の式sndr
とenv
に対して、sender-for<decltype((sndr)), when_all_with_variant_t> == false
のとき、式when_all_with_variant.transform_sender(sndr, env)
は不適格となる。
そうでなければ、式when_all_with_variant.transform_sender(sndr, env)
は下記と等価。
auto&& [_, _, ...child] = sndr;
return when_all(into_variant(std::forward_like<decltype((sndr))>(child))...);
カスタマイゼーションポイント
Senderアルゴリズム構築時に、全入力Senderに関連付けられた共通の実行ドメインCD
に対してexecution::transform_sender
経由でSender変換が行われる。
デフォルト実行ドメインでは無変換。
Receiverとの接続(connect)時に、関連付けられた実行ドメインに対してexecution::transform_sender
経由でSender変換が行われる。
デフォルト実行ドメインではwhen_all_with_variant.transform_sender(sndr, env)
が呼ばれ、前述仕様通りのSenderへと変換される。
例
#include <print>
#include <string>
#include <execution>
namespace ex = std::execution;
// MySenderは下記いずれかの完了操作を行う
// 値完了 set_value(int), set_value(string)
// エラー完了 set_error(int)
struct MySender {
using sender_concept = ex::sender_t;
using completion_signatures = ex::completion_signatures<
ex::set_value_t(int),
ex::set_value_t(std::string),
ex::set_error_t(int)
>;
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 {
using namespace std::string_literals;
switch (val_) {
case 1:
ex::set_value(std::move(rcvr_), 100);
break;
case 2:
ex::set_value(std::move(rcvr_), "C++"s);
break;
default:
ex::set_error(std::move(rcvr_), val_);
break;
}
}
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 snd1 = MySender{1};
ex::sender auto snd2 = MySender{2};
ex::sender auto sndr = ex::when_all_with_variant(snd1, snd2);
auto result = std::this_thread::sync_wait(sndr);
// result := optional<
// tuple<
// variant<tuple<int>, tuple<string>>,
// variant<tuple<int>, tuple<string>>
// >
// >型
auto [val1, val2] = result.value();
// val1,val2 := variant<tuple<int>, tuple<string>>型
struct DumpVal {
void operator()(std::tuple<int> n) {
std::println("(int) {}", get<0>(n));
}
void operator()(std::tuple<std::string> s) {
std::println("(str) {}", get<0>(s));
}
};
std::visit(DumpVal{}, val1);
std::visit(DumpVal{}, val2);
}
出力
(int) 100
(str) C++
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??