c++ 是否有必要在返回void的协程的每个执行路径上都有co_return语句

zazmityj  于 2022-11-19  发布在  其他
关注(0)|答案(2)|浏览(145)

我想知道下面的代码是否是有效的C++代码,或者如果不使用co_return会导致未定义的行为。

IAsyncAction MyClass::MyCoroutine()
{
  co_await someOtherClassInstance.SomeCoroutine();
}

即是否需要调整代码如下?

IAsyncAction MyClass::MyCoroutine()
{
  co_await someOtherClassInstance.SomeCoroutine();
  co_return;
}

如果行为不是未定义的,最佳实践是什么(始终添加co_return或不添加)?这样做的理由是什么?

bkkx9g8r

bkkx9g8r1#

省略co_return;语句在这里定义得很好。根据[stmt.return.coroutine],只要p.return_void()是一个有效的表达式(其中p是承诺类型),这是允许的。
C++/WinRT为IAsyncActionIAsyncActionWithProgress实现了return_void()(或者更确切地说,为它们实现了内部await适配器结构)。
由于co_return;语句在这里是完全可选的,所以是否使用它取决于个人偏好。个人而言,我更喜欢阅读存在co_return;语句的代码,原因如下:

  • 它允许我很容易地注解掉协程的一部分(例如,用于测试),而不必冒险将它变成一个常规函数。
  • 我不必了解复杂的C++/WinRT库的复杂性,就可以判断代码是否正确。
  • 如果我决定更改代码的返回类型,代码将保持正确。
fkaflof6

fkaflof62#

根据cppreference,如果Promise类型没有Promise::return_void()成员函数,则第一个块仅在未定义的行为中发生:
当协程到达co_return语句时,它执行以下操作:

  • 调用promise.return_void()
  • co_return;
  • co_return expr,其中expr的类型为void
    *从返回空的协程的末尾落下。在这种情况下,如果Promise类型没有Promise::return_void()**成员函数,则该行为未定义。

标准草案似乎也是这么说的:

**如果p.return_­void()是一个有效的表达式,流出协程的函数体的结尾等价于没有操作数的co_­return;**否则流出协程函数体的末尾会导致未定义的行为。

[在两个引号中强调我的]

相关问题