我注意到以下代码都被MSVC 和 GCC接受(下面是缩短的 TLDR 版本):
template<typename T>
struct Generator {
struct promise_type {
std::suspend_always initial_suspend() {
return {};
}
std::suspend_always final_suspend() noexcept {
return {};
}
auto get_return_object() {
return Generator{ std::coroutine_handle<promise_type>::from_promise(*this) };
}
std::suspend_always yield_value(T value) {
current_value = value;
return {};
}
void return_void() {}
void unhandled_exception() {
std::exit(1);
}
T current_value;
};
Generator(std::coroutine_handle<promise_type> h): coro(h) {}
std::coroutine_handle<promise_type> coro;
~Generator() {
if (coro) coro.destroy();
}
Generator(const Generator&) = delete;
Generator& operator = (const Generator&) = delete;
Generator(Generator&&) = delete;
Generator& operator = (Generator&&) = delete;
T operator()() {
coro.resume();
return coro.promise().current_value;
}
};
Generator<int> getNext() {
int value = 0;
while (true) {
co_yield value;
value++;
}
}
int main() {
Generator<int> gen = getNext();
for (int i = 0; i <= 2; ++i) {
int val = gen();
std::cout << "val: " << val << std::endl;
}
}
TLDR 版本:
template<typename T>
struct Generator {
struct promise_type {
//...
};
//...
Generator(const Generator&) = delete;
Generator& operator = (const Generator&) = delete;
Generator(Generator&&) = delete;
Generator& operator = (Generator&&) = delete;
//...
};
Generator<int> getNext() {
//...
}
int main() {
Generator<int> gen = getNext();
//...
}
但是,我想知道 C++20 标准是否允许这样做。通常,如果删除复制和移动函数,则函数无法检索类型:
struct MyType
{
MyType() {}
MyType(const MyType&) = delete;
MyType& operator = (const MyType&) = delete;
MyType(MyType&&) = delete;
MyType& operator = (MyType&&) = delete;
};
MyType generateType()
{
MyType val;
return val; // <--- Compile Error
}
乍一看,这一行似乎也使用了已删除的函数: Generator<int> gen = getNext();
协程允许这样做吗?如果是,标准的哪一部分允许?
我相信该Generator
对象是通过调用来检索的get_return_object()
,它返回一个纯右值。从 C++17 开始,这需要强制复制省略。参见 cppreference.com:
在以下情况下,编译器需要省略类对象的复制和移动构造,即使复制/移动构造函数和析构函数具有可观察到的副作用。对象被直接构建到存储中,否则它们将被复制/移动到那里。复制/移动构造函数不需要存在或可访问:
在 return 语句中,当操作数是与函数返回类型相同类类型(忽略 cv 限定)的纯右值时:
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句