最終更新日時(UTC): 2026年05月16日 15時17分02秒
yoh が更新

履歴 編集

customization point object
<execution>

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

    namespace std::execution {
      struct then_t { unspecified };
      inline constexpr then_t then{};
    }

## 概要

`then`は、入力Senderの値完了操作の継続として関数呼び出しをアタッチするSenderアダプタである。

`then`はパイプ可能Senderアダプタオブジェクトであり、パイプライン記法をサポートする。

本ページにてSenderアルゴリズム`then`／`upon_error`／`upon_stopped`の動作仕様を包括的に説明するため、以降のセクションにおいては`then-cpo`, `set-cpo`をそれぞれ下記の通りとする。

`then-cpo` | `set-cpo`
--- | ---
`then` | `set_value`
`upon_error` | `set_error`
`upon_stopped` | `set_stopped`

## 効果

説明用の式`sndr`と`f`に対して、`decltype((sndr))`が`sender`を満たさない、もしくは`decltype((f))`が`movable-value`を満たさないとき、呼び出し式`then-cpo(sndr, f)`は不適格となる。

そうでなければ、呼び出し式`then-cpo(sndr, f)`は下記と等価。

    make-sender(then-cpo, f, sndr)

### Senderアルゴリズムタグ `then-cpo`

Senderアルゴリズム動作説明用のクラステンプレート`impls-for`に対して、下記の特殊化が定義される。

    namespace std::execution {
      template<>
      struct impls-for<decayed-typeof<then-cpo>> : default-impls {
        static constexpr auto complete =
          []<class Tag, class... Args>
            (auto, auto& fn, auto& rcvr, Tag, Args&&... args) noexcept -> void {
              if constexpr (same_as<Tag, decayed-typeof<set-cpo>>) {
                TRY-SET-VALUE(rcvr,
                              invoke(std::move(fn), std::forward<Args>(args)...));
              } else {
                Tag()(std::move(rcvr), std::forward<Args>(args)...);
              }
            };

        template<class Sndr, class... Env>
        static consteval void check-types();
      };
    }

メンバ関数`impls-for<decayed-typeof<then-cpo>>::check-types`の効果は下記の通り。

    auto cs = get_completion_signatures<child-type<Sndr>, FWD-ENV-T(Env)...>();
    auto fn = []<class... Ts>(decayed-typeof<set-cpo>(*)(Ts...)) {
      if constexpr (!invocable<remove_cvref_t<data-type<Sndr>>, Ts...>)
        throw unspecified-exception();
    };
    cs.for-each(overload-set{fn, [](auto){}});

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

Receiver接続時に、関連付けられた実行ドメインに対して`execution::transform_sender`経由でSender変換が行われる。 デフォルト実行ドメインでは無変換。

戻り値のSender `out_sndr`が下記を満たさない場合、呼び出し式`then-cpo(sndr, f)`の動作は未定義となる。

- `then-cpo`に対する`sndr`の`set-cpo`結果データで`f`またはそのコピーを呼び出し、`out_sndr`の値完了として`f`の結果値を用いること。
- 上記以外の完了操作では変更なしに転送すること。

## 例

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

    int main()
    {
      { // 関数呼び出し
        ex::sender auto snd0 = ex::just('C', 2);
        ex::sender auto snd1 = ex::then(snd0, [](char ch, int n) {
          return ch + std::string(n, '+');
        });
        auto [s] = std::this_thread::sync_wait(snd1).value();
        std::println("{}", s);
      }

      { // パイプライン記法
        ex::sender auto sndr = ex::just('C', 2);
          | ex::then([](char ch, int n) {
              return ch + std::string(n, '+');
            });
        auto [s] = std::this_thread::sync_wait(sndr).value();
        std::println("{}", s);
      }
    }

### 出力

    C++
    C++

## バージョン

### 言語

- C++26

### 処理系

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

## 関連項目

- `execution::upon_error`
- `execution::upon_stopped`

## 参照

- P2300R10 `std::execution`
- P3557R3 High-Quality Sender Diagnostics with Constexpr Exceptions
- LWG4369 `check-types` function for `upon_error` and `upon_stopped` is wrong
- P3826R5 Fix Sender Algorithm Customization