C++协程的return_void和return_value的return类型

C++ coroutine's return_void's and return_value's return type

return_void

考虑下面协程的 ReturnObject 并注意方法前的注释 ReturnObject::promise_type::return_void :

struct ReturnObject {
        struct promise_type {
            int val_{23};
            ReturnObject get_return_object() {
                return {std::coroutine_handle<promise_type>::from_promise(*this)}; 
            }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void unhandled_exception() {}

         /*** NOTE THIS ***/
        //void return_void(){  }
        
        /*** AND THIS ***/
        int return_void(){ return 101; }
      };
      
      std::coroutine_handle<promise_type> h_; 
      ReturnObject(std::coroutine_handle<promise_type> h):h_{h}{ } 
      operator std::coroutine_handle<promise_type>() const { return h_; } 
};

compiler explorer

上的完整代码

Web 和 this paper(第 37 页)中的标准用法表明 return_void 方法 returns void 但在 gcc 11.2 中,return_voidint return 类型也适用。这个对吗 ?如果是,

  1. 为什么它同时适用于 void 和非 void return 类型?
  2. 在非空 return 类型的情况下,return_void 的 return 值会发生什么变化?

return_value

在 gcc 中可以观察到与方法 return_value 类似的效果。 如果是 return_value 的 returned 数据,有没有办法直接访问这个 returned 数据,类似于正常的 subroutine/function 的 returned 值 ?

检查 compiler explorer

上的代码

更新:

在@useless 的建议下,我将 [[nodiscard]] 添加到具有非空 return 类型的 return_voidreturn_value 并启用了 -Wall 标志。

令人惊讶的是 return_voidreturn_value 我什至没有收到 gcc-10.2 的警告。检查 here but gcc-11.2 gives me a warning (here)

我得到的 return_value int return 类型的 compiler warning 如下所示

warning: ignoring return value of 'int ReturnObject::promise_type::return_value(int)', declared with attribute 'nodiscard' [-Wunused-result]
   31 |     co_return 7;
      |               ^
<source>:18:27: note: declared here
   18 |         [[nodiscard]] int return_value(int val){return val;}

我不相信编译器警告 co_returns 值被丢弃。实际上,被丢弃的 return 值来自方法 return_value,但编译器设法 以某种方式隐藏它

感谢您查看 post 并提前提出建议。

[stmt.return.coroutine]/2 表示表达式

promise_object.return_value(...)

promise_object.return_void()

co_return 使用的那个)应为 void.

类型

因此任一函数的return类型必须是void(如果它被co_return使用)。

MSVC 确实正确地拒绝了程序:

<source>(31): error C7625: The type of a coroutine promise return_value or return_void expression must be void
<source>(18): note: see declaration of 'ReturnObject::promise_type::return_value'