“协程的 Promise 必须声明 'return_value' 或 'return_void'”错误 Visual Studio 2019 C++ 20

问题描述 投票:0回答:2

VS2019最新c++编译器。

错误是:“协程的 Promise 必须声明 'return_value' 或 'return_void'”

来自 David Mazières 的示例 https://www.scs.stanford.edu/~dm/blog/c++-coroutines.html 博客 在不同的编译器 GCC 10.2 下工作。

我无法获取源代码在VS2019中编译。

#include <concepts>
#include <coroutine>
#include <exception>
#include <iostream>
struct ReturnObject {
    struct promise_type {
        ReturnObject get_return_object() { return {}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return{}; }
        void unhandled_exception() {}
        
    };
};

struct Awaiter {
    std::coroutine_handle<>* hp_;
    constexpr bool await_ready() const noexcept { return false; }
    void await_suspend(std::coroutine_handle<> h) { *hp_ = h; }
    constexpr void await_resume() const noexcept {}
};

ReturnObject
counter(std::coroutine_handle<>* continuation_out)
{
    Awaiter a{ continuation_out };
    for (unsigned i = 0;; ++i) {
        co_await a;
        std::cout << "counter: " << i << std::endl;
    }
}

void
main1()
{
    std::coroutine_handle<> h;
    counter(&h);                
    for (int i = 0; i < 100; ++i) {
        std::cout << "In main1 function\n";
        h();
    }
    h.destroy();
}

我错过了什么? C++ 协程新手。谁不是?

c++ visual-studio-2019 c++20 c++-coroutine
2个回答
9
投票

两个编译器都是正确的。当 Promise 类型没有

return_void
时,从协程末尾流出是未定义的行为:

[stmt.return.coroutine]/3:

如果

p.return_­void()
是有效表达式,则从协程末尾流出相当于没有操作数的
co_­return
;否则从协程末尾流出会导致未定义的行为。

您可以在 Promise 类型中定义 noop

return_void
以获得您想要的行为:

void return_void() noexcept {}

0
投票

我认为 MSVC 是不正确的。

stmt.return.coroutine#3

如果在 Promise 类型范围内搜索名称

return_void
找到任何声明,则从协程函数体末尾流出相当于没有操作数的
co_return
;否则从协程函数体的末尾流出会导致未定义的行为。

未定义的行为不是格式错误。只要控制流永远到达就可以了。

考虑以下示例:

repeat
永远不会
co_return
也不会到达其函数体的末尾,因此它不应该需要
return_void

#include <coroutine>

struct promise;

struct coro: std::coroutine_handle<promise> {
    using promise_type = ::promise;
};

struct promise {
    int value;
    coro get_return_object() { return {coro::from_promise(*this)}; }
    std::suspend_always initial_suspend() noexcept { return {}; }
    std::suspend_always final_suspend() noexcept { return {}; }
    std::suspend_always yield_value(int x) { value = x; return {}; }
    void unhandled_exception() {}
    // void return_void() {}
};

coro repeat(int value) {
    while (true) {
        co_yield value;
    }
    // unreachable
}

int main() {
    auto c = repeat(42);
    for (int i = 0; i < 100; ++i) {
        c.resume();
    }
    c.destroy();
}
© www.soinside.com 2019 - 2024. All rights reserved.