【问题标题】:How to return a value from a coroutine using co_return?如何使用 co_return 从协程返回值?
【发布时间】:2021-07-16 13:30:47
【问题描述】:

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

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

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

协程也会返回一个空向量,尽管 value 不为空。

如何从协程返回值而不将其包装在包含 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;
}

【问题讨论】:

  • 嗯,第一个问题是您对协程特征的专业化不依赖于任何用户提供的类型,因此您的程序格式不正确。将 this 的隐式参数添加到它。 ;)
  • 二、替换“但是get_return_object()中的向量是按值返回的,不起作用。” “它不起作用”,并完整描述了发生的情况,以及与您想要的不符的原因。 “它不起作用”是不够的。
  • “问题是协程只返回了std::vector get_return_object()的结果。”等等,什么?这是怎么回事?
  • @Yakk-AdamNevraumont,问题是get_return_object()返回的值不能被return_value函数重新填充,因为它是按值返回的。而且我不知道如何不通过get_return_object从协程返回结果。
  • 帮自己一个忙,用写的东西。目前大约有 3-4 个成熟的库可供选择。

标签: c++ asynchronous c++20 coroutine


【解决方案1】:

std::vector&lt;int&gt; 不是可等待类型,因此它不能用作协程的返回对象。

如果你add some tracing,你可以看到操作顺序出错了。

get_return_object 需要返回一些可以在稍后给出std::vector&lt;int&gt; 的东西。例如。如果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(); }
};

【讨论】:

  • 请告诉我如何在代码中发布它
  • 即为了得到promise的结果,是需要通过co_await调用协程,还是在promise类中创建一个返回结果的方法?
  • main 不能是协程。
  • @Yakk-AdamNevraumont 我co_await主要的部分,或者如果vecstd::vector&lt;int&gt;,则解释co_await vec是非首发?
  • @Caleth OP 的代码中没有co_await vec。协程是一种函数,返回std::vector的函数可以是协程。它必须有另一个参数(包括成员函数的 this),但它可以是协程。
猜你喜欢
  • 2020-11-07
  • 1970-01-01
  • 2021-08-17
  • 2013-09-07
  • 2020-12-08
  • 1970-01-01
  • 2022-07-05
  • 2020-04-20
  • 1970-01-01
相关资源
最近更新 更多