【发布时间】:2021-12-30 18:53:47
【问题描述】:
来自著名的 C++ 协程库(在源文件generator.hpp 中搜索“Don't allow any use of co_await inside the generator coroutine.”)和我自己的实验,我知道协程使用co_yield不能同时使用co_await。
既然使用co_yield 的生成器必须是同步的,那么使用co_yield 相对于简单的有状态 lambda 有什么优势?
例如:
#include <iostream>
generator<int> g()
{
for (auto i = 0; i < 9; ++i)
{
co_yield i;
}
}
int main()
{
auto fn_gen = [i = 0] mutable { return i++; };
// Lambda way
for (auto i = 0; i < 9; ++i)
{
std::cout << fn_gen() << std::endl;
}
// co_yield way
for (auto i : g())
{
std::cout << i << std::endl;
}
}
co_yield 与 C++20 中的简单有状态 lambda 相比有何特殊价值?
请查看更新后的 MWE:https://godbolt.org/z/x1Yoen7Ys
在更新后的示例中,当在同一个协程中使用co_await 和co_yield 时,输出完全出乎意料。
【问题讨论】:
-
你完全可以在同样使用
co_yield的函数中使用co_await。甚至还有legitimate use cases for it。 -
简短回答:视情况而定。对于一个简单的生成器,状态完整的 lambda 可能更可取。但是协程生成器在更复杂的情况下可能会更简单,因为状态不像计数器那么简单。例如,目录中文件的递归迭代器。
-
我在 clang-13 上测试过,使用
co_await和co_yield会导致意外的resume订单。也许这是协程实现中的一个错误。 -
@xmllmx:您必须显示测试用例中使用的全部代码,包括协程机器类型。显然,cppcoro 的
generator类型有一个明确的机制,可以将尝试通过软管连接到发电机内部的co_await。 -
嗯,一方面,这两个示例并不等同。在很多方面。生成器为您提供从 0 到 8 的数字。lambda 为您提供从 0 到...的数字。您可以调用
g()两次,第二次从 0 开始,您必须复制 @987654341 @ 在您完全调用它以获得该行为之前。等
标签: c++ c++20 coroutine language-design c++-coroutine