8

我正在使用C++/WinRT为 UWP 控件编写 C++ 协程:

winrt::fire_and_forget MyControl::DoSomething()
{
    if (/* some condition */)
    {
         // Why does this work?!
         return;
    }

    co_await winrt::resume_foreground(Dispatcher());

    // Do some stuff

    co_return;
}

这是为我编译的,但据我所知,C++ 协程不允许普通return语句。这是编译器中的错误吗?

(有趣的是,我无法将 to 更改co_returnreturn;我收到编译器错误。是否仅在a or must be之后返回语句?)co_awaitco_yieldco_return

4

1 回答 1

10

这似乎是 MSVSC 的遗留实现。MSVSC 在标准正式完成之前就实现了协程,因此有两种异步/async/async:strict)实现。我似乎打开了旧的、不符合标准的版本。

标准很清楚,您不能return在协程中使用普通语句(强调添加):

协程不能使用可变参数、普通返回语句或占位符返回类型(auto 或 Concept)。constexpr 函数、构造函数、析构函数和主函数不能是协程。

https://en.cppreference.com/w/cpp/language/coroutines

您可以通过一个简单的示例(在 Godbolt 中查看)来验证这是一种遗留行为:

// ... boilerplate to make std::futures awaitable ...
// via https://stackoverflow.com/a/70406948/788168

std::future<int> compute_value()
{
    if (rand() > 5)
    {
        // Shouldn't work:
        return 5;
    }

    int result = co_await std::async([] { return 30; });

    co_return result;
}

int main() {
    compute_value();
}

使用x64 msvc v19.latest编译器和/std:c++20标志,我们得到这个错误:

example.cpp
<source>(38): error C3773: Use of 'return' in this context is a non-conforming extension in C++20
<source>(38): note: Please use '/await' command-line option to enable relevant extensions
Compiler returned: 2

所以,回答问题:

这是为我编译的,但据我所知,C++ 协程不允许普通return语句。这是编译器中的错误吗?

(有趣的是,我无法将 to 更改co_returnreturn;我收到编译器错误。是否仅在a or must be之后返回语句?)co_awaitco_yieldco_return

这不是编译器中的错误,它只是一个非标准实现。如果您使用标准实现(使用/async:strictor /std:c++20),则该简单return语句将无法编译。符合标准的协程永远不能使用简单的 return 语句。

于 2022-01-20T19:57:30.203 回答