最終更新日時: 2026年07月22日 16時08分23秒 (JST)
rotarymars が更新

履歴 編集

customization point object
<execution>

# std::execution::when_all_with_variant(C++26)

    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))...`とする。

下記いずれかが`true`となるとき、呼び出し式`when_all_with_variant(sndrs...)`は不適格となる。

- `sizeof...(sndrs) == 0`、または
- `(sender<Sndrs> && ...) == false`

そうでなければ、呼び出し式`when_all_with_variant(sndrs...)`は下記と等価。

    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(set_value, sndr, env)`は不適格となる。

そうでなければ、式`when_all_with_variant.transform_sender(set_value, sndr, env)`は下記と等価。

    auto&& [_, _, ...child] = sndr;
    return when_all(into_variant(std::forward_like<decltype((sndr))>(child))...);

## カスタマイゼーションポイント

Receiverとの接続(connect)時に、関連付けられた実行ドメインに対して`execution::transform_sender`経由でSender変換が行われる。 デフォルト実行ドメインでは`when_all_with_variant.transform_sender(set_value, sndr, env)`が呼ばれ、前述仕様通りのSenderへと変換される。

## 例

    #include <print>
    #include <string>
    #include <execution>
    #include <tuple>
    #include <utility>
    namespace ex = std::execution;

    // MySenderは下記いずれかの完了操作を行う
    //   値完了     set_value(int), set_value(string)
    //   エラー完了 set_error(int)
    struct MySender {
      using sender_concept = ex::sender_tag;

      using completion_signatures = ex::completion_signatures<
        ex::set_value_t(int),
        ex::set_value_t(std::string),
        ex::set_error_t(int)
      >;
      template <typename Self>
      static consteval auto get_completion_signatures()
      {
        return completion_signatures{};
      }

      template <typename Rcvr>
      struct state {
        using operation_state_concept = ex::operation_state_tag;

        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++: ??

## 関連項目

- `execution::when_all`
- `execution::into_variant`

## 参照

- P2300R10 `std::execution`
- P3557R3 High-Quality Sender Diagnostics with Constexpr Exceptions
- P3826R5 Fix Sender Algorithm Customization