Reputation: 305
In the code below, I am trying to return from a coroutine std :: vector . The problem is that only the result of the std::vector<int> get_return_object()
is returned from the coroutine.
When the co_return statement is executed, method void return_value(std::vector<int>&& value)
is called, which fills the vector returned by method get_return_object()
. But the vector from get_return_object()
is returned by value and it doesn't work. When I try to do so
std::vector<int> return_value(std::vector<int>&& value){
return value
}
An empty vector is also returned from the coroutine, although value is not empty.
How to return a value from a coroutine without wrapping it in a Task containing a promise_object?
exemple:
#include "coroutine"
#include "iostream"
struct Promise {
std::vector<int> vec;
std::vector<int> get_return_object() {
return vec;
}
std::suspend_never initial_suspend() {
return {};
}
std::suspend_never final_suspend() {
return {};
}
void return_void() {}
void return_value(std::vector<int>&& value){
vec = std::move(value);
}
void unhandled_exception() { std::terminate(); }
};
template<typename... Args>
struct std::coroutine_traits<std::vector<int>, Args...>{
using promise_type = Promise;
};
class Caller{
public:
std::vector<int> call();
};
std::vector<int> Caller::call() {
co_return std::vector<int>{1, 2, 3, 4};
}
int main(){
Caller c;
auto vec = c.call();
std::cout << vec.size();
return 0;
}
Upvotes: 2
Views: 1897
Reputation: 63152
std::vector<int>
is not an awaitable type, so it can't usefully be the return object of a coroutine.
If you add some tracing, you can see the order of operations going wrong.
get_return_object
needs to return something that can be given a std::vector<int>
later. E.g. if all users of Promise
never suspend:
struct Promise {
struct result {
std::future<std::vector<int>> fut;
operator std::vector<int>() { return fut.get(); }
};
std::promise<std::vector<int>> prom;
result get_return_object() {
std::cout << "get_return_object" << std::endl;
return { prom.get_future() };
}
std::suspend_never initial_suspend() {
std::cout << "initial_suspend" << std::endl;
return {};
}
std::suspend_never final_suspend() {
std::cout << "final_suspend" << std::endl;
return {};
}
void return_void() {}
void return_value(std::vector<int>&& value){
std::cout << "return_value" << std::endl;
prom.set_value(std::move(value));
}
void unhandled_exception() { std::terminate(); }
};
Upvotes: 2