我一直在玩C ++ 20协程,并尝试将我的一些代码库移到使用它们。不过,我遇到了一个问题,因为似乎新的协程似乎无法复制。这些generator
对象已删除了复制构造函数和复制赋值运算符,而我研究的内容似乎都没有办法。
能做到吗?
作为参考,我编写了一个小测试程序,尝试复制C ++ 20协程失败,并且尝试成功执行相同的操作boost::asio::coroutine
。这使用的是Visual Studio 2019版本16.3.7
#include <sdkddkver.h>
#include <string>
#include <algorithm>
#include <iterator>
#include <experimental\resumable>
#include <experimental\generator>
#include <cassert>
#include <boost\asio\yield.hpp>
namespace std_coroutines {
auto letters() {
for (auto c = 'a'; ; ++c)
co_yield c;
}
void run() {
auto gen = letters();
std::string s1, s2;
std::copy_n(gen.begin(), 3, std::back_inserter(s1)); // append "abc" to s1
//auto gen_copy = gen; // doesn't compile
std::copy_n(gen.begin(), 3, std::back_inserter(s1)); // append "def" to s1
//std::copy_n(gen_copy.begin(), 3, std::back_inserter(s2)); // append "def" to s2
assert(s1 == "abcdef");
assert(s2 == "def"); // fails
}
};// namespace std_coroutines
namespace boost_asio_coroutines {
struct letters : boost::asio::coroutine {
char c = 'a';
char operator()() {
reenter(this) for (;; ++c)
{
yield return c;
}
}
};
void run() {
auto gen = letters();
std::string s1, s2;
std::generate_n(std::back_inserter(s1), 3, std::ref(gen)); // append "abc" to s1
auto gen_copy = gen;
std::generate_n(std::back_inserter(s1), 3, std::ref(gen)); // append "def" to s1
std::generate_n(std::back_inserter(s2), 3, std::ref(gen_copy)); // append "def" to s2
assert(s1 == "abcdef");
assert(s2 == "def");
}
} // namespace boost_asio_coroutines
int main() {
boost_asio_coroutines::run();
std_coroutines::run();
}
TS并未明确禁止复制。如您所述,std::experimental::generator
promise对象已删除复制操作。我认为最初的实现对于副本还是比较保守的,因为有很多需要考虑的地方。
协同程序管理的句柄协程的激活上下文,正式称为协同程序状态的N4775。此状态是在堆还是堆栈上(出于优化原因)是实现定义的。协程存储本身的格式也是实现定义的。
只要沿着shared_ptr
和确立了协程句柄的所有权语义,该实现就可以实现浅表复制weak_ptr
(类比有所分散,因为只有一个协程是该状态的实际所有者,而所有其他协程都是观察者) 。
如果您要询问深层副本,那么您最终会得到两个互不影响的独立生成器,那么我想所有的含义也是有可能的。
我可以想到的一些含义:
*协程存储通过调用全局非数组new
函数获得。从理论上讲,您可以重载此函数以匹配协程,但是由于存储是实现定义的,因此您必须了解您的平台。尽管如此,从理论上讲,这仍将允许您利用已保留堆栈大块的全局区域分配器
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句