In first part of the issue, Painless C++ Coroutine Part-1, the we laid out all the components that are needed to instantiate a compilable coroutine.
In the second part of the issue, Painless C++ Coroutine Part-2, the demonstrations continued to explain the technique to resume a suspended coroutine by understanding the coroutine handle and its relation with the promise type object. Following this, the huge but important detour was taken to understand awaiter and awaitable objects by creating the custom awaiters.
I continue the journey to finally reveal how to return the data to the caller of the coroutine in section 7 and finally a lazy generator using coroutine in section 8.
This is the exciting part where all the coroutine customization can be used in one place, but it has to be broken down to assimilatable and incremental chunks to manage the complexity. These incremental chunks are divided in three parts:
and finally
3.** Connecting foo to main.**
awaiter
and the foo
At the conclusion of section 6.1, it was mentioned that the return type of expression co_await expr
is same as that of awaiter::await_resume
which till this point has been void
. Fortunately standard doesn’t place any restriction on what the return type of await_resume
should be and one can return anything from it and catch the returned data as a result of the evaluation of co_await expr
expression and the returned value can be used within the coroutine. The example below (note the usage of a custom suspend_never
awaiter object):
struct suspend_never{
...
double await_resume() const noexcept {return 10.234;}
};
ReturnObject foo(){
double val = co_await suspend_never{};
std::cout << val << "\n";
}
int main()
{
std::coroutine_handle<> h = foo();
}
//stdout: 10.234
The working code can be found here.
One can try to persist the value val
returned by co_await suspend_never{}
expression over multiple suspend-resume of coroutine by returning pointer or reference from suspend_never::await_resume
but since the operand suspend_never{}
to co_await
is a temporary, every time the coroutine is resumed, the suspend_never::val_
is destroyed along with the temporary object.
#modern-cpp #cpp20 #coroutine #cxx #c++