February 1st, 2021

Why am I being told my fire_and_forget coroutine is not returning a value?

You’re writing a C++/WinRT coroutine that nominally returns a fire_and_forget, meaning that the coroutine runs without notifying anybody when it is finished.

fire_and_forget DoSomething()
{ 
    DoFirstThing();
    DoSecondThing();
}

And when you compile this, you get

error C4716: 'DoSomething': must return a value

A fire_and_forget coroutine doesn’t have a return value, since there is nobody awaiting it. So what’s going on here?

What’s going on is that the body of your fire_and_forget coroutine doesn’t contain any co_await or co_return statements. A function must contain at least one co_await or co_return statement in order to be considered a coroutine. Since the function did neither of those things, the C++ language treats it not as a coroutine but a regular function.

A regular function that needs to return a fire_and_forget object, and you didn’t do that.

You have a few options for fixing this.

One option is to add a co_return; statement at the end. Normally, falling off the end of a coroutine is equivalent to performing a co_return;, but in this case, you need to say co_return explicitly in order to make sure you have a coroutine at all!

Another option is to change your function to return void. After all, it doesn’t contain any asynchronous operations, so the whole thing ran synchronously anyway. It never needed to be a coroutine in the first place.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

3 comments

Discussion is closed. Login to edit/delete existing comments.

  • Alexis Ryan

    Guessing confusion came from documentation not being clear enough that fire_and_forget is actually a type

  • Charles Milette

    Or if you really want to run this asynchronously, use

    co_await winrt::resume_background();
    • 紅樓鍮 · Edited

      Or rather double check whether DoFirstThing and DoSecondThing are async APIs and remember to co_await their return values… (although it’s generally good practice to co_await resume_background() first anyways)