Search code examples
c++coroutinec++-winrtc++-coroutine

Is it necessary to have a co_return statement on each execution path of a coroutine that returns void


I wonder whether the below code is valid C++ code or if not using co_return results in undefined behavior.

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

I.e. is it necessary to adjust the code as follows?

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

If the behavior is not undefined, what is the best practice (always add co_return or not) and what is the justification for doing so?


Solution

  • Omitting the co_return; statement is well defined here. According to [stmt.return.coroutine] this is allowed as long as p.return_void() is a valid expression (where p is the promise type).

    C++/WinRT implements return_void() for IAsyncAction and IAsyncActionWithProgress (or rather the internal await adapter structs for those).

    Since the co_return; statement is purely optional here, it is down to personal preference on whether to use it or not. Personally, I prefer reading code where the co_return; statement is present, for a few reasons:

    • It allows me to easily comment out part of the coroutine (e.g. for testing) without risking to turn it into a regular function.
    • I don't have to know the intricacies of the complex C++/WinRT library to figure out whether the code is correct.
    • The code stays correct if I ever decide to change its return type.