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

履歴 編集

class template
<execution>

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

namespace std::execution {
  template<class-type Promise>
  struct with_awaitable_senders {
    template<class OtherPromise>
      requires (!same_as<OtherPromise, void>)
    void set_continuation(coroutine_handle<OtherPromise> h) noexcept;

    coroutine_handle<> continuation() const noexcept { return continuation; }

    coroutine_handle<> unhandled_stopped() noexcept {
      return stopped-handler(continuation.address());
    }

    template<class Value>
    see below await_transform(Value&& value);

  private:
    [[noreturn]] static coroutine_handle<>
      default-unhandled-stopped(void*) noexcept {  // exposition only
      terminate();
    }

    coroutine_handle<> continuation{};                       // exposition only
    coroutine_handle<> (*stopped-handler)(void*) noexcept =  // exposition only
      &default-unhandled-stopped;
  };
}

概要

with_awaitable_sendersは、コルーチンPromise型の基底クラスとして利用することで、Senderco_await演算子でAwait可能とするクラステンプレートである。

またunhandled_stoppedのデフォルト実装を提供し、Senderがset_stoppedを呼び出して停止完了したとき、Await式からキャッチできない "停止" 例外が送出されたかのように取り扱う。

メンバ関数

名前 説明 対応バージョン
(constructor) コンストラクタ C++26
(destructor) デストラクタ C++26
set_continuation 継続ハンドラを設定する C++26
continuation 継続ハンドラを返す C++26
unhandled_stopped 停止ハンドラを返す C++26
await_transform co_await演算子へアダプトしAwaitableオブジェクトを返す C++26

静的メンバ関数

名前 説明 対応バージョン
default-unhandled-stopped 説明専用のデフォルト停止ハンドラ C++26

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

template<typename T>
class Lazy {
public:
  struct promise_type;
  using value_type = T;
  using handle_type = std::coroutine_handle<promise_type>;

  struct promise_type : ex::with_awaitable_senders<promise_type> {
    value_type value_;
    auto get_return_object() { return Lazy{handle_type::from_promise(*this)}; }
    auto initial_suspend() noexcept { return std::suspend_always{}; }
    auto final_suspend() noexcept { return std::suspend_always{}; }
    void unhandled_exception() { throw; }
    void return_value(value_type v) noexcept { value_ = v; }
  };

private:
  Lazy(handle_type h) : coro_{h} {}

public:
  Lazy(Lazy&& rhs)
    : coro_{std::exchange(rhs.coro_, nullptr)} {}
  Lazy& operator=(Lazy&& rhs) {
    if (coro_) { std::exchange(coro_, nullptr).destroy(); }
    std::swap(rhs.coro_, coro_);
    return *this;
  }
  ~Lazy()
    { if (coro_) { coro_.destroy(); } }

  value_type get() {
    assert(coro_);
    if (!coro_.done()) {
      coro_.resume();
    }
    return coro_.promise().value_;
  }

private:
  handle_type coro_;
};

// SenderをAwait可能なコルーチン
Lazy<int> coro(int n)
{
  std::println("coro start");
  ex::sender auto sndr =
    ex::just(n)
    | ex::then([](int m){ return m * 3; });

  // Senderを開始して値取得を待機
  int val = co_await sndr;

  std::println("coro end");
  co_return val * 7;
}

int main()
{
  try {
    auto task = coro(2);
    std::println("get");
    auto value = task.get();
    std::println("value={}", value);
  } catch (...) {
    std::println("<exception>");
  }
}

出力

get
coro start
coro end
value=42

バージョン

言語

  • C++26

処理系

関連項目

参照