【发布时间】:2022-01-09 13:49:51
【问题描述】:
在以下代码示例中,lambda 协程 g 执行 co_await f,其中 f 是协程返回类型,删除了复制和移动构造函数:
#include <coroutine>
class task {
public:
class task_promise {
public:
task get_return_object() { return task{handle_type::from_promise(*this)}; }
auto initial_suspend() { return std::suspend_always{}; }
auto final_suspend() noexcept { return std::suspend_never{}; }
void return_void() {}
void unhandled_exception() {}
};
using handle_type = std::coroutine_handle<task_promise>;
handle_type handle;
auto await_ready() { return false; }
auto await_suspend(handle_type) { return handle; }
void await_resume() { handle.resume(); }
using promise_type = task_promise;
task(handle_type h) : handle(h) {}
task(const task&) = delete;
task& operator=(const task&) = delete;
task(task&&) = delete;
task& operator=(task&&) = delete;
};
int main() {
task f = []() -> task { co_return; }();
task g = [&f]() -> task { co_await f; }();
g.handle.resume();
}
代码在 MSVC 中被接受,但在 GCC 中不被接受。
GCC 11.2 抱怨缺少移动构造函数:
error: use of deleted function 'task::task(task&&)'
和 GCC 主干 - 在缺少的复制构造函数上:
error: use of deleted function 'task::task(const task&)'
演示:https://gcc.godbolt.org/z/1c7fajqn8
哪个编译器在这里?
附:有一个相关的问题Why must the return type of a coroutine be move-constructible? 但是
- 该问题已在 GCC 10.2 中修复,而此问题中的示例在 GCC 11 和中继中仍然有效;
- 这个问题问的是
co_await的要求,而另一个根本没有提到co_await; - 另一个问题仅与移动构造函数有关,而最新的 GCC 需要复制构造函数。
【问题讨论】:
-
您可能有兴趣关注 clang 编译器的以下错误:github.com/llvm/llvm-project/issues/53098
-
@JVApen 注意the OP themselves posted that bug report.
-
"该问题在 GCC 10.2 中已修复,而此问题中的示例在 GCC 11 和中继中仍然有效;" 那么它没有修复,是吗? “这个问题询问了 co_await 的要求,而另一个根本没有提到 co_await;” 你为什么认为这很相关?
co_await与返回值的性质无关。 “另一个问题只是关于 move-constructor,而最新的 GCC 要求使用 copy-constructor。” 你认为这很重要吗?
标签: c++ language-lawyer c++20 coroutine