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_return
statement, it performs the following:
- calls
promise.return_void()
for
co_return;
co_return expr
whereexpr
has 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_return
with no operand; otherwise flowing off the end of a coroutine's function-body results in undefined behavior.
[Emphasis mine in both quotes]