如何解决C ++:如何正确使用#include <协程>中可用的generator <>,task <>和lazy <>类?
我从here收集到的协程类型大致分为3种:
generator ,task 和lazy
我的问题是:如果要确定返回类型,这三者之间有什么区别?
例如:延迟加载一组文件处理程序的协同例程的返回类是什么?我的实现将使用task<FileHandler>
和generator<Filehandler>
来达到相同的目的。
我在“执行”部分下查看了promise object
与协程互动时对function SamplePrevArrow(props) {
const { currentSlide,className,onClick } = props;
if (currentSlide === 0) {
return false;
} else {
return <div className={className} onClick={onClick} />;
}
}
的限制。但是我只能找到实现上的差异,而不是方法上的差异。
解决方法
我做了一些研究,我相信答案如下:
首先,C ++中没有lazy<>
类。 https://en.cppreference.com/w/cpp/language/coroutines有错。 (请参阅草稿进行确认)
因此,generator<T>
和task<T>
的返回类型之间存在区别。
TLDR;
最容易记住的方法是:
相关联
generators
与co_yield
关联;而tasks
与co_await
发电机
与generator类相关联的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>
概念,因此请确保您正确使用与这两个概念相关的约束。等待者概念包括以下约束:await_ready
,await_suspend
和await_resume
。可等待的概念有以下限制:(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));
}
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。