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?
CodePudding user response:
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.
CodePudding user response:
According to cppreference, the first block would only incur in undefined behaviour if the Promise type has no Promise::return_void() member function:
When a coroutine reaches the
co_returnstatement, it performs the following:
- calls
promise.return_void()for
co_return;co_return exprwhereexprhas type void- falling off the end of a void-returning coroutine. The behavior is undefined if the Promise type has no
Promise::return_void()member function in this case.
The Standard draft seems to say the same in other words:
If
p.return_void()is a valid expression, flowing off the end of a coroutine's function-body is equivalent to aco_returnwith no operand; otherwise flowing off the end of a coroutine's function-body results in undefined behavior.
[Emphasis mine in both quotes]
