Search code examples
c++c++20c++-coroutinec++-templates

Why does template not discard the co_return?


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?

Full code with an implementation of the promise type


Solution

  • 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.