Since the Coroutines TS has been accepted into C++20 at the ISO meeting at Kona, I started playing around with them a bit for myself. Clang already has decent support for coroutines but the implementation of the library support is still lacking. In particular, the Awaitable types such as std::future
, std::generator
, etc. have not been implemented yet.
Thus, I took it upon myself to make std::future
awaitable. I largely followed the talk by James McNellis at CppCon 2016, specifically this slide:
This being 2019, I actually had some trouble with the (presumably untested?) code on this slide:
- It seems to me overloading
operator co_await
is not a thing anymore? Instead one should use the optionalawait_transform
of thepromise_type
. Not sure I got this right, though. - The
then
continuation of the future captures the handle by value, but theresume
member function is not const-qualified. I worked around this by making the lambdamutable
.
Also, then
and is_ready
are not available in std::future
but are part of std::experimental::future
which is still missing from my libc++ version. To avoid dealing with the Awaiter and to implement future continuations, I wrote a derived future class which is Awaitable and an Awaiter. It is my understanding that eventually both would also be true of std::future
. You can see my example on Compiler Explorer. It does compile.
However, it also does segfault. This happens in await_resume
when get()
is called. This is actually not surprising since valid()
returns false
at that point (making the call to get()
UB). I think this is because when then
is used to continue the future, the original future object is moved into the async future, thus invalidating the old future (*this
at the time await_resume
is called, so after the move). My implementation of then
is loosely inspired by this answer and this code I found on GitHub. Those may not be ideal, but cppreference explicitly states valid() == false
as a postcondition of calling then
, so I believe it is correct to move out of the original future.
What am I missing here? This "bug" seems present already in the above slide. How can I reconcile this issue? Does anybody know of a (working) existing implementation of an Awaitable future? Thanks.
std::future
can be made awaitable. – Septennial