我做了一些研究,我相信答案如下:
首先,C++ 中没有lazy<> 类。 https://en.cppreference.com/w/cpp/language/coroutines 错了。 (参考草稿确认)
所以,generator<T> 和 task<T> 的返回类型是有区别的。
TLDR;
最容易记住的方法是:
generators 与co_yield 相关联;而tasks 与co_await 相关联
生成器
与生成器类关联的 co_yield 机制与我们在 python 中遇到的完全相同(请参阅文档),也与操作系统机制中的thread_suspend 概念非常相似。
您可以选择同步或异步实现它。 (有关示例,请参阅cppcoro library。)
生成器类型(种类)如下所示:
struct generator {
struct promise_type;
using handle = std::coroutine_handle<promise_type>;
struct promise_type {
int current_value;
static auto get_return_object_on_allocation_failure() { return generator{nullptr}; }
auto get_return_object() { return generator{handle::from_promise(*this)}; }
auto initial_suspend() { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_always{}; }
void unhandled_exception() { std::terminate(); }
void return_void() {}
auto yield_value(int value) {
current_value = value;
return std::suspend_always{};
}
};
bool move_next() { return coro ? (coro.resume(), !coro.done()) : false; }
int current_value() { return coro.promise().current_value; }
generator(generator const&) = delete;
generator(generator && rhs) : coro(rhs.coro) { rhs.coro = nullptr; }
~generator() { if (coro) coro.destroy(); }
private:
generator(handle h) : coro(h) {}
handle coro;
};
您将使用如下生成器类型:
generator f() { co_yield 1; co_yield 2; }
任务
另一方面,任务与co_await 表达式相关联。它需要Awaitable<T> 和Awaiter<T> 概念,因此请确保正确使用与这两个概念相关的约束。 Awaiter 概念包括以下约束:await_ready、await_suspend 和 await_resume。 Awaitable 概念有以下约束:(1) co_await 特化/重载和 (2) await_transform 没有重载。[ ref ]
任务类型如下所示:
class task
{
public:
using promise_type = <unspecified>;
using value_type = T;
task() noexcept;
task(task&& other) noexcept;
task& operator=(task&& other);
task(const task& other) = delete;
task& operator=(const task& other) = delete;
bool is_ready() const noexcept;
Awaiter<T&> operator co_await() const & noexcept;
Awaiter<T&&> operator co_await() const && noexcept;
Awaitable<void> when_ready() const noexcept;
};
您可以选择使用这些概念(最好是我的方法),或者如果您还不熟悉这些概念的存在,那么您可能需要自己实现相关的约束来实现。
使用任务就像[ref]:
task<> tcp_echo_server() {
char data[1024];
for (;;) {
size_t n = co_await socket.async_read_some(buffer(data));
co_await async_write(socket, buffer(data, n));
}
}