xml*_*lmx 6 c++ language-design coroutine c++20 c++-coroutine
从著名的C++协程库(在源文件generator.hpp中搜索“Don'tallowanyuseof insidethegeneratorcoroutine co_await.” ),以及我自己的实验,我知道一个协程使用不能同时使用。co_yieldco_await
既然使用的生成器必须是同步的,那么与简单的有状态 lambda 相比co_yield,使用有什么优势呢?co_yield
例如:
#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;
}
}
Run Code Online (Sandbox Code Playgroud)
与 C++20 中的简单有状态 lambda 相比,的特殊价值是什么?co_yield
请参阅更新的 MWE:https ://godbolt.org/z/x1Yoen7Ys
在更新的示例中,在同一协程中使用co_await和时,输出完全出乎意料。co_yield
对于具有最少内部状态和代码的简单生成器,一个小的函子或 lambda 就可以了。但是,随着生成器代码变得更加复杂并且需要更多状态,它就会变得不那么精细。您必须在函子类型或 lambda 说明符中添加更多成员。函数内部的代码越来越大。ETC。
在最极端的情况下,co_yield基于 - 的生成器可以向外界隐藏其所有实现细节,只需将其定义放在 .cpp 文件中即可。有状态函子无法隐藏其内部状态,因为其状态是外部世界必须看到的类型的成员。避免这种情况的唯一方法是通过类型擦除,例如使用std::function. 到那时,你基本上不会比仅仅使用co_yield.
另外,co_await可以与 一起使用co_yield。Cppcoro 的generator类型明确地管理它,但 cppcoro 不是 C++20。您可以编写任何您想要的生成器,并且该生成器可以支持特定用途的使用co_await。
事实上,您可以制作异步生成器,有时您可以立即生成一个值,有时您可以通过某些异步过程安排值的可用性。调用异步生成器的代码可以co_await从中提取值,而不是将其视为函子或迭代器对。