I was doing some experiments with the proposed c++ co-routines that are currently experimental in VS2017. I simply wanted to have a co-routine that doesn't return anything but calls co_await on some co-routine object that, let's say, does some processing on another thread before resuming. However, VS will not compile even the most rudimentary co-routine program that returns void. For instance:
#include "stdafx.h"
#include <experimental\coroutine>
using namespace std::experimental;
void bob()
{
co_await suspend_always{};
}
int main()
{
bob();
}
results in the errors:
1>c:\\program files (x86)\\microsoft visual studio\\2017\\professional\\vc\\tools\\msvc\\14.10.25017\\include\\experimental\\resumable(46): error C2825: '_Ret': must be a class or namespace when followed by '::' 1>d:\\dev\\coroutinestest\\main.cpp(10): note: see reference to class template instantiation 'std::experimental::coroutine_traits' being compiled 1>c:\\program files (x86)\\microsoft visual studio\\2017\\professional\\vc\\tools\\msvc\\14.10.25017\\include\\experimental\\resumable(46): error C2510: '_Ret': left of '::' must be a class/struct/union 1>c:\\program files (x86)\\microsoft visual studio\\2017\\professional\\vc\\tools\\msvc\\14.10.25017\\include\\experimental\\resumable(46): error C2061: syntax error: identifier 'promise_type' 1>c:\\program files (x86)\\microsoft visual studio\\2017\\professional\\vc\\tools\\msvc\\14.10.25017\\include\\experimental\\resumable(46): error C2238: unexpected token(s) preceding ';'
Now I assume that this error is due to void::promise_type being nonsensical, however why is the promise type even being instantiated when there's nothing to return? I would expect to be able to return nothing from a co-routine. Is this just a current bug in the implementation or am I misunderstanding the use of co-routines.
Thanks
Of course it CAN return void
. The reason it doesn't is - no one implements the coroutine protocol for void
. You can implement it on your own. The coroutine protocol for a return type is satisfied by providing a specialization for coroutine_traits
.
To make void
a valid return type for coroutines, you can do this:
namespace std::experimental
{
template<class... T>
struct coroutine_traits<void, T...>
{
struct promise_type
{
void get_return_object() {}
void set_exception(exception_ptr const&) noexcept {}
bool initial_suspend() noexcept
{
return false;
}
bool final_suspend() noexcept
{
return false;
}
void return_void() noexcept {}
};
};
}
This allows your example to compile.
However, note that in your example, calling co_await suspend_always{};
will cause memory leak, this is because coroutine_handle
is much like a raw-pointer, and you're on your own to ensure the coroutine gets destroyed.
As a side note, the coroutine emulation library CO2 , however, takes another decision - its co2::coroutine
has unique-ownership, so a call to CO2_AWAIT(suspend_always{});
won't leak memory, it just cancels the coroutine.
I stumbled across this question when trying to debug compiler error messages. The solution for me was to make the function return an IAsyncAction
instead of returning void
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.