Non-void Coroutine Without Return Statement

459 views Asked by At

I am trying to wrap my head around the C++ coroutine feature. I read Kenny's article (C++ - Introducing C++/WinRT) and also tried watching this presentation, CppCon 2016: James McNellis “Introduction to C++ Coroutines". I keep seeing non-void "functions" without some form of return statement. As an example, see the following code sample from Kenny's article. The PrintFeedAsync function/coroutine has an IAsyncAction return type but there is no return statement in the definition. could someone explain how this works?

IAsyncAction PrintFeedAsync()
{
    Uri uri(L"http://kennykerr.ca/feed");
    SyndicationClient client;
    SyndicationFeed feed = co_await client.RetrieveFeedAsync(uri);
    for (SyndicationItem item : feed.Items())
    {
        hstring title = item.Title().Text();
        printf("%ls\n", title.c_str());
    }
}

int main()
{
    initialize();
    PrintFeedAsync().get();
}
1

There are 1 answers

0
jgawrych On

For a function to be a coroutine, its return type has to have certain traits defined that describes how the coroutine will work. C++/WinRT defines those traits for their version of IAsyncAction or IAsyncOperation<TResult>. Specifically, there are two methods that handle returning from a coroutine: return_value(...) or return_void(). IAsyncOperation uses the former, and IAsyncAction uses the latter.

Looking at the latest coroutine spec at the time of this answer, we find what happens if there is no co_return statement in the body of a coroutine function:

If p.return_void() is a valid expression, flowing off the end of a coroutine is equivalent to a co_return with no operand; otherwise flowing off the end of a coroutine results in undefined behavior.

"Programming Languages – C++ Extensions for Coroutines" (N4680) § 6.6.3.1/3

Since C++/WinRT defines a return_void for IAsyncAction's traits then the compiler will follow the above rule. At the end where execution flows off the end of the coroutine, the return_void method is used, the same as if you ended the function with co_return;. If we look at the definition of return_void, we see it's equivalent to setting the status as Completed and calling the completion handler if there is one.