【问题标题】:Must coroutine return type be copy- or move-constructible if it is passed in co_await如果在 co_await 中传递协程返回类型,则它必须是可复制或可移动构造的
【发布时间】: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
  • "该问题在 GCC 10.2 中已修复,而此问题中的示例在 GCC 11 和中继中仍然有效;" 那么它没有修复,是吗? “这个问题询问了 co_await 的要求,而另一个根本没有提到 co_await;” 你为什么认为这很相关? co_await 与返回值的性质无关。 “另一个问题只是关于 move-constructor,而最新的 GCC 要求使用 copy-constructor。” 你认为这很重要吗?

标签: c++ language-lawyer c++20 coroutine


【解决方案1】:

这是一个编译器bug。具体来说,

如果 o 是纯右值,则应用临时实现转换 (7.3.4) -- co_await 7.6.2.3

这基本上意味着它应该使用 RVO 就地构建。

【讨论】:

    猜你喜欢
    • 2020-10-07
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    • 2020-09-20
    • 2015-04-09
    相关资源
    最近更新 更多