如何使用 co_return 从协程中 return 一个值?

How to return a value from a coroutine using co_return?

在下面的代码中,我试图从协程 std::vector return。问题是只有 std::vector<int> get_return_object() 的结果是 return 来自协程的。

当执行co_return语句时,调用方法void return_value(std::vector<int>&& value),填充由方法get_return_object()编辑的向量return。但是来自 get_return_object() 的向量是 return 按值编辑的,它不起作用。当我尝试这样做时

std::vector<int> return_value(std::vector<int>&& value){
    return value
}

空向量也从协程中 return 生成,尽管值不为空。

如何 return 协程中的值而不将其包装在包含 promise_object 的任务中?

例子:

#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;
}

std::vector<int> 不是可等待类型,因此它不能用作协程的 return 对象。

如果你add some tracing,你会发现操作顺序出错了。

get_return_object 需要 return 稍后可以给 std::vector<int> 的东西。例如。如果 Promise 的所有用户从不暂停:

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(); }
};