此MCVE不能在g++10 (带有-std=c++21 -fcoroutines选项)中编译。
#include <iostream>
int f() { for (int i = 0; i < 10; ++i) co_yield i; }
int main ()
{
for (int i : f())
std::cout << i << ' ';
return 0;
}f的第一行应该是什么样子,这样我才能得到一个可工作的协程?或者需要做一些其他的事情来创建一个工作的协程?它需要是C++20 ( g++10是supposed to fully support)的一部分,而不是一个附加库。
发布于 2020-06-26 06:02:54
这是一个使用gcc 10.1的最小工作示例,它是一个只使用co_yield而没有co_return的协程myCoroutineFunction
它使用了counted for循环。range for循环需要更多的工作来编写迭代器。
协程的返回类型是一个生成器对象,它需要一个promise对象来跟踪协程的当前值。
因为生成器和promise相互依赖,所以可以方便地使promise成为生成器的嵌套类。
每次协程产生一个值时,该值由promise维护,而协程被挂起
客户端代码与生成器交互,生成器提供访问当前协程程序值和在挂起后推进协程程序的方法
// coroutine.cpp
// g++ -ocoroutine -g -O0 -Wall -Werror -Wextra
// -std=c++20 -fcoroutines -fno-exceptions coroutine.cpp
#include <stdio.h>
#include <coroutine>
using namespace std;
struct Generator {
struct Promise;
// compiler looks for promise_type
using promise_type=Promise;
coroutine_handle<Promise> coro;
Generator(coroutine_handle<Promise> h): coro(h) {}
~Generator() {
if(coro)
coro.destroy();
}
// get current value of coroutine
int value() {
return coro.promise().val;
}
// advance coroutine past suspension
bool next() {
coro.resume();
return !coro.done();
}
struct Promise {
// current value of suspended coroutine
int val;
// called by compiler first thing to get coroutine result
Generator get_return_object() {
return Generator{coroutine_handle<Promise>::from_promise(*this)};
}
// called by compiler first time co_yield occurs
suspend_always initial_suspend() {
return {};
}
// required for co_yield
suspend_always yield_value(int x) {
val=x;
return {};
}
// called by compiler for coroutine without return
suspend_never return_void() {
return {};
}
// called by compiler last thing to await final result
// coroutine cannot be resumed after this is called
suspend_always final_suspend() {
return {};
}
};
};
Generator myCoroutineFunction(int n) {
for(int i = 0; i < n; ++i) {
co_yield i;
}
}int main ()
{
int n=10;
Generator myCoroutineResult = myCoroutineFunction(n);
for(int i=0; i < n; ++i) {
myCoroutineResult.next();
printf("%d ", myCoroutineResult.value());
}
return 0;
}编译和运行
$ g++ -ocoroutine -g -O0 -Wall -Werror -Wextra \
-std=c++20 -fcoroutines -fno-exceptions coroutine.cpp
$ ./coroutine
0 1 2 3 4 5 6 7 8 9发布于 2020-09-06 18:27:37
从你的问题看:
,f的第一行应该是什么样子,这样我才能得到一个工作协程?
我已经修改了你的代码如下。请特别注意f的返回类型。
Couroutine_Example_Generator<int> f() { for (int i = 0; i < 10; ++i) co_yield i; }
int main ()
{
for (auto i = f(); i.move_next(); )
{
std::cout << i.current_value() << ' ';
}
return 0;
}您可以看到我对您的代码所做的更改的完整的Godbolt代码。检查here。
,或者是否需要做一些其他的事情才能使协程正常工作?
是。C++20规范要求提供promise_type。因此,我在一个头类中定义了生成器的模板化版本,您可以将其视为here。或者在我的repository中查看稍微不同的代码示例。
如果您感兴趣,请提供更多相关详细信息。下面是C++20规范的相关摘录
协程的promise类型是std::coroutine_traits::promise_type.协程的行为就好像它的函数体被替换为:
{
promise-type promise promise-constructor-arguments ;
try {
co_await promise .initial_suspend() ;
function-bodyhttps://stackoverflow.com/questions/62564094
复制相似问题