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型の基底クラスとして利用することで、Senderをco_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
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??