Reputation: 1229
I have tried to compile coroutine example from the CppCon presentation https://youtu.be/ZTqHjjm86Bw?t=560
Unfortunately compilation fails:
$ g++-10 -pedantic -Wall -std=c++20 -fcoroutines main.cpp
main.cpp: In function ‘std::future<int> compute_value()’:
main.cpp:7:16: error: unable to find the promise type for this coroutine
7 | int result = co_await std::async([]
| ^~~~~~~~
At the beginning presenter warns that what he is about to present is just a proposal. So it makes me confused: can std::future
be return from a coroutine, or do I just try to call it incorrectly?
Full code:
#include <coroutine>
#include <iostream>
#include <future>
std::future<int> compute_value(){
int result = co_await std::async([]
{
return 30;
});
co_return result;
}
int main() {
std::cout << compute_value().get() << std::endl;
}
Upvotes: 4
Views: 3262
Reputation: 473946
There are (basically1) no standard library types in C++20 that implement the necessary coroutine machinery to make coroutines work. This includes std::promise<T>
/std::future<T>
.
You could write wrappers for them that implement the coroutine machinery though.
1: There are support types like std::suspend_always
/std::suspend_never
which have coroutine machinery, but they don't really do anything like what you're thinking of.
Upvotes: 7
Reputation: 822
In C++20 a user should manually enable the use of std::future<T>
as a coroutine type. A minimal complete example for std::future<int>
:
#include <coroutine>
#include <future>
#include <iostream>
template <>
struct std::coroutine_traits<std::future<int>> {
struct promise_type : std::promise<int> {
std::future<int> get_return_object() { return this->get_future(); }
std::suspend_never initial_suspend() noexcept { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_value(int value) { this->set_value(value); }
void unhandled_exception() {
this->set_exception(std::current_exception());
}
};
};
auto operator co_await(std::future<int> future) {
struct awaiter : std::future<int> {
bool await_ready() { return false; } // suspend always
void await_suspend(std::coroutine_handle<> handle) {
std::thread([this, handle]() {
this->wait();
handle.resume();
}).detach();
}
int await_resume() { return this->get(); }
};
return awaiter{std::move(future)};
}
std::future<int> compute_value() {
int result = co_await std::async([] { return 30; });
co_return result;
}
int main() { std::cout << compute_value().get() << std::endl; }
Reference: https://en.cppreference.com/w/cpp/coroutine/coroutine_traits
Upvotes: 2