9

I am writing a C++ coroutine for a UWP control using C++/WinRT:

winrt::fire_and_forget MyControl::DoSomething()
{
    if (/* some condition */)
    {
         // Why does this work?!
         return;
    }

    co_await winrt::resume_foreground(Dispatcher());

    // Do some stuff

    co_return;
}

This is compiling for me, but as far as I know, C++ coroutines do not allow plain return statements. Is this a bug in the compiler?

(Interestingly, I cannot change the co_return to return; I get a compiler error. Is it that only return statements after a co_await or co_yield must be co_return?)

Disclaimer: I work for Microsoft.

1 Answer 1

12

This seems to be a legacy implementation for MSVSC. MSVSC implemented coroutines before the standard was formally complete, so there are two implementations of async (/async and /async:strict). I seem to have the old, non–standard-compliant version turned on.

The standard is clear that you cannot use plain return statements in coroutines (emphasis added):

Coroutines cannot use variadic arguments, plain return statements, or placeholder return types (auto or Concept). Constexpr functions, constructors, destructors, and the main function cannot be coroutines.

https://en.cppreference.com/w/cpp/language/coroutines

You can verify that this is a legacy behavior with a simple example (view in Godbolt):

// ... boilerplate to make std::futures awaitable ...
// via https://stackoverflow.com/a/70406948/788168

std::future<int> compute_value()
{
    if (rand() > 5)
    {
        // Shouldn't work:
        return 5;
    }

    int result = co_await std::async([] { return 30; });

    co_return result;
}

int main() {
    compute_value();
}

With the x64 msvc v19.latest compiler and the /std:c++20 flag, we get this error:

example.cpp
<source>(38): error C3773: Use of 'return' in this context is a non-conforming extension in C++20
<source>(38): note: Please use '/await' command-line option to enable relevant extensions
Compiler returned: 2

So, to answer the questions:

This is compiling for me, but as far as I know, C++ coroutines do not allow plain return statements. Is this a bug in the compiler?

(Interestingly, I cannot change the co_return to return; I get a compiler error. Is it that only return statements after a co_await or co_yield must be co_return?)

It's not a bug in the compiler, it's just a non-standard implementation. If you use the standard implementation (with /async:strict or /std:c++20), that plain return statement will not compile. Standards-compliant coroutines cannot use plain return statements, ever.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.