I'd like to make a function with both sync and coroutine version, without using template specialization, i.e. with an if constexpr
.
This is the function I wrote:
template <Async _a>
AsyncResult<int, _a> func(int a) {
if constexpr (_a == Async::Disable)
return a;
else
co_return a;
}
But when I instantiate the true branch it gives an error
auto a = func<Async::Disable>(1); // compiler error
auto b = func<Async::Enable>(2); // ok
error: unable to find the promise type for this coroutine
Why is this not working?
The standard explicitly says this is not possible. As per Note 1 in stmt.return.coroutine#1
... A coroutine shall not enclose a return statement ([stmt.return]).
[Note 1: For this determination, it is irrelevant whether the return statement is enclosed by a discarded statement ([stmt.if]). — end note]
So you won't be able to return from a coroutine even if it's in a discarded statement. You can specialize the function template instead of using if constexpr
.
template <Async _a>
AsyncResult<int, _a> func(int a)
{
co_return a;
}
template <>
AsyncResult<int, Async::Disable> func<Async::Disable>(int a)
{
return a;
}
Here's a demo.