最終更新日時(UTC):
が更新

履歴 編集

customization point object
<execution>

std::execution::stopped_as_error(C++26)

namespace std::execution {
  struct stopped_as_error_t { unspecified };
  inline constexpr stopped_as_error_t stopped_as_error{};
}

概要

stopped_as_errorは、入力Sender停止完了をカスタムエラー型のエラー完了にマップするSenderアダプタである。

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

効果

説明用の式sndrerrに対して、型Sndrdecltype((sndr))、型Errdecltype((err))とする。Sndrsenderを満たさない、もしくはErrmoveable-valueを満たさないとき、呼び出し式stopped_as_error(sndr, err)不適格となる。

そうでなければ、呼び出し式stopped_as_error(sndr, err)sndrが1回だけ評価されることを除いて、下記と等価。

transform_sender(get-domain-early(sndr), make-sender(stopped_as_error, err, sndr))

Senderアルゴリズムタグ stopped_as_error

説明用の式sndrenvに対して、型Sndrdecltype((sndr))、型Envdecltype((env))とする。sender-for<Sndr, stopped_as_error_t> == falseのとき、式stopped_as_error.transform_sender(sndr, env)不適格となる。

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

auto&& [_, err, child] = sndr;
using E = decltype(auto(err));
return let_stopped(
    std::forward_like<Sndr>(child),
    [err = std::forward_like<Sndr>(err)]() mutable noexcept(is_nothrow_move_constructible_v<E>) {
      return just_error(std::move(err));
    });

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

Senderアルゴリズム構築時に、Sendersndr関連付けられた実行ドメインに対してexecution::transform_sender経由でSender変換が行われる。 デフォルト実行ドメインでは無変換。

Receiverとの接続(connect)時に、関連付けられた実行ドメインに対してexecution::transform_sender経由でSender変換が行われる。 デフォルト実行ドメインではstopped_as_error.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_error(snd0, MyStoppedError{});
    try {
      auto [result] = std::this_thread::sync_wait(snd1).value();
      std::println("(int) {}", result);
    } catch (MyStoppedError) {
      std::println("stopped");
    }
  }

  { // パイプライン記法
    ex::sender auto sndr =
      MySender{-1}
      | ex::stopped_as_error(MyStoppedError{});
    try {
      auto [result] = std::this_thread::sync_wait(sndr).value();
      std::println("(int) {}", result);
    } catch (MyStoppedError) {
      std::println("stopped");
    }
  }
}

出力

stopped
stopped

バージョン

言語

  • C++26

処理系

関連項目

参照