从著名的C++协同器库(搜索“不要允许在生成器协同线内使用co_await”)。在源文件generator.hpp中,从我自己的实验中,我知道使用co_yield的协同线不能同时使用co_await。
由于使用co_yield的生成器必须是同步的,那么,与简单的有状态lambda相比,使用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;
}
} co_yield 与C++20中简单的有状态lambda相比有什么特殊价值?
请参阅更新的MWE:https://godbolt.org/z/x1Yoen7Ys
在更新的示例中,当在同一个协同线中使用co_await和co_yield时,输出是完全出乎意料的。
发布于 2021-12-30 19:16:07
对于具有极小内部状态和代码的平凡生成器,一个小函子或lambda很好。但是当您的生成器代码变得更加复杂,需要更多的状态时,它就变得不那么精细了。你必须把更多的成员放在你的函子类型或你的羔羊说明。函数中有越来越大的代码。等。
在最极端的情况下,co_yield-based生成器可以向外部世界隐藏其所有实现细节,只需将其定义放在.cpp文件中即可。有状态函子不能隐藏它的内部状态,因为它的状态是类型的成员,外部世界必须看到。避免这种情况的唯一方法是通过类型擦除,例如使用类似于std::function的东西。在这一点上,仅仅使用co_yield基本上没有什么收获。
此外,co_await也可以与co_yield一起使用。cppcoro的generator类型显式地使用它,但是cppcoro不是C++20,你可以编写任何你想要的生成器,而那个生成器可以为特定目的。
实际上,您可以制作异步生成器,有时可以立即生成一个值,有时还可以用某些异步进程来安排值的可用性。调用异步生成器的代码可以在其上co_await以从中提取值,而不是将其视为函子或迭代器对。
https://stackoverflow.com/questions/70535616
复制相似问题