最終更新日時: 2026年05月17日 00時17分02秒 (JST)
yoh が更新

履歴 編集

customization point object
<execution>

# std::this_thread::sync_wait_with_variant(C++26)

    namespace std::this_thread {
      struct sync_wait_with_variant_t { unspecified };
      inline constexpr sync_wait_with_variant_t sync_wait_with_variant{};
    }

## 概要

`sync_wait_with_variant`は、入力Senderが完了するまで現在のスレッドをブロックし、非同期操作の結果を取得するSenderコンシューマである。

`sync_wait_with_variant`は入力Senderが複数の値完了シグネチャを持つケースに対応する。 値完了シグネチャが1個だけの場合は`sync_wait`アルゴリズムを利用する。

入力Senderの値完了シグネチャが`set_value_t(Ts0...)`, ..., `set_value_t(TsN...)`のとき、`sync_wait_with_variant`の結果型は`optional<variant<tuple<Ts0...>, ..., tuple<TsN...>>`となる。

## 効果

説明用の`sndr`を`decltype(into_variant(sndr))`が`Sndr`型となる式とする。

型`Domain`を`get_completion_domain<set_value_t>(get_env(sndr), sync-wait-env{})`として、呼び出し式`this_thread::sync_wait_with_variant(sndr)`は下記と等価。

    apply_sender(Domain(), sync_wait_with_variant, sndr)

- `sender_in<Sndr, sync-wait-env> == true`であること。
- 型`sync-wait-with-variant-result-type<Sndr>`が適格であること。
- 上記の`apply_sender`式を`e`としたとき、`same_as<decltype(e), sync-wait-with-variant-result-type<Sndr>> == true`であること。

### 結果型

`sync_wait_with_variant`の結果型となる、説明専用のエイリアステンプレート`sync-wait-with-variant-result-type`を下記の通り定義する。

    namespace std::this_thread {
      template<execution::sender_in<sync-wait-env> Sndr>
      using sync-wait-with-variant-result-type =
        optional<execution::value_types_of_t<Sndr, sync-wait-env>>;
    }

### Senderアルゴリズムタグ `sync_wait_with_variant`

説明用の`sndr`を`decltype(into_variant(sndr))`が`Sndr`型となる式とする。

式`sync_wait_with_variant.apply_sender(sndr)`は下記と等価。

    using result_type = sync-wait-with-variant-result-type<Sndr>;
    if (auto opt_value = sync_wait(into_variant(sndr))) {
      return result_type(std::move(get<0>(*opt_value)));
    }
    return result_type(nullopt);

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

入力Sender `sndr`の完了ドメイン `dom`に対して、 `execution::apply_sender`経由で`dom.apply_sender(sync_wait_with_variant, sndr)`が呼ばれる。

デフォルト実行ドメインでは、`sync_wait_with_variant.apply_sender(sndr)`が呼ばれる。

下記を満たさない場合、呼び出し式`this_thread::sync_wait_with_variant(sndr)`の動作は未定義となる。

- 指定したSenderが完了するまで、前方進行保証委任(forward progress guarantee delegation)による現在のスレッドをブロックすること。
- 指定したSenderの非同期操作の結果が返る場合
  - 値完了の場合、結果データは`optional`オブジェクト内の`tuple`の`variant`で返されること。
  - エラー完了の場合、例外を送出すること。
  - 停止完了の場合、無効値`optional`オブジェクトが返されること。

## 例

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

    int main()
    {
      // 値(100, 'X')を送信するSender
      ex::sender auto sndr = ex::just(100, 'X');
      // メインスレッド上で完了待機
      auto result = std::this_thread::sync_wait_with_variant(sndr);
      // 結果型optional<variant<tuple<int,char>>>からtupleを取り出す
      auto tup = get<0>(result.value());
      std::println("result={}", tup);
    }

### 出力

    result=(100, 'X')

## バージョン

### 言語

- C++26

### 処理系

- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??

## 関連項目

- `execution::sender`
- `this_thread::sync_wait`

## 参照

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