gpt4 book ai didi

c++ - `co_yield` 能否在协程恢复时从调用方返回一个值?

转载 作者:行者123 更新时间:2023-12-01 14:22:37 26 4
gpt4 key购买 nike

C++20 引入了协程,可以用来创建生成器和其他类似的东西:

generator<int> counter(int max) {
for(int i = 0; i < max; i++) {
co_yield i;
}
}

有没有办法创建一个协程,以便调用者可以在协程恢复后提供 co_yield 返回的响应?让我们称其为 channel 而不是生成器。

这是我希望能够做的一个例子:
channel<int, int> accumulator(int initial) {
while(true) {
// Can channel be written so co_yield provides a response?
int response = co_yield initial;
initial += response;
}
}

在这里,每当调用者恢复协程时,它都会提供一个值,一旦协程恢复,该值就会从 co_yield 返回,如下所示:
std::vector<int> accumulate(std::vector<int> values) {
channel<int, int> acc = accumulator(0);

std::vector<int> summed_values;

for(int v : values) {
// Get whatever value was yielded by the accumulator
int sum = acc.recieve();
// Do something with the value
summed_values.push_back(sum);
// Resume the accumulator, returning this value from co_yield:
acc.send(v);
}
return summed_values;
}

根据评论编辑

任何人都可以提供有关如何执行此操作的一些指导或示例吗?协程对我来说仍然很陌生。我有一个 channel 类的基本实现,但我不确定应该从 yield_value 返回什么才能实现这一点。

我在评论中标记了 (A)(B) 的两个有问题的位置。
template <class Out, class In>
struct channel {
struct promise_type {
Out current_value;
auto yield_value(Out value) {
current_value = value;
// (A) What do I return here?
}
channel get_return_object() {
return {std::coroutine_handle<promise_type>::from_promise(*this)};
}
// We run up until the first value is ready
auto initial_suspend() noexcept { return std::suspend_never(); }
auto final_suspend() noexcept { return std::suspend_always(); }
void unhandled_exception() noexcept { std::terminate(); }
};


Out receive() {
return handle.promise().current_value;
}
void send(In response) {
// (B) What do I do here?
}
// Constructors, destructor and move assignment operator omitted for brevity
private:
std::coroutine_handle<promise_type> handle = nullptr;
};

最佳答案

关键是 await_resume ,在 awaiter(yield_value 的结果)上调用它来获取 co_yield 的结果。

您还需要将响应存储在某处。正如 Raymond Chen 在 comment 中建议的那样,您可以将该值放入 promise_type 的新数据成员中。

所以变化是:

  • promise_type 添加数据成员。
    In response;
  • 定义一个自定义的 awaiter 以返回该数据成员。
    struct awaiter : std::suspend_always {
    friend promise_type;
    constexpr In await_resume() const { return m_p->response; }

    private:
    constexpr awaiter(promise_type* p) : m_p(p) {}
    promise_type* m_p;
    };
  • (A) 中,返回自定义的 awaiter。
    return awaiter(this);
  • (B) 中,设置数据成员,然后恢复协程。
    handle.promise().response = response;
    handle.resume();
  • 关于c++ - `co_yield` 能否在协程恢复时从调用方返回一个值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62354960/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com