为什么VS2017协程不能返回void?

AKB*_*AKB 2 c++ coroutine visual-studio visual-studio-2017

我正在使用目前在 VS2017 中进行实验的提议的 c++ 协程进行一些实验。我只是想拥有一个不返回任何内容的协同例程,而是在某个协同例程对象上调用 co_await,比方说,在恢复之前在另一个线程上进行一些处理。然而,VS 甚至不会编译返回 void 的最基本的协程程序。例如:

#include "stdafx.h"
#include <experimental\coroutine>

using namespace std::experimental;

void bob()
{
    co_await suspend_always{};
}

int main()
{
    bob();
}
Run Code Online (Sandbox Code Playgroud)

导致错误:

1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.10.25017\include\experimental\resumable(46): error C2825: '_Ret': must be a class or后跟'::'时的命名空间 1>d:\dev\coroutinestest\main.cpp(10):注意:请参阅对正在编译的类模板实例化 'std::experimental::coroutine_traits' 的引用 1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.10.25017\include\experimental\resumable(46):错误 C2510:'_Ret':'::' 的左边必须是一个类/结构/union 1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.10.25017\include\experimental\resumable(46):错误 C2061:语法错误:标识符“promise_type” 1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.10.25017\include\experimental\resumable(46): 错误 C2238: ';' 之前的意外标记

现在我假设这个错误是由于 void::promise_type 是无意义的,但是为什么在没有任何返回的情况下甚至会实例化 promise 类型?我希望能够从协程中返回任何内容。这只是实现中的当前错误还是我误解了协同程序的使用。

谢谢

Jam*_*ree 5

当然可以返回void。没有的原因是 - 没有人为void. 你可以自己实现它。返回类型的协程协议通过为 提供特化来满足coroutine_traits

void为协程设置有效的返回类型,您可以这样做:

namespace std::experimental
{
    template<class... T>
    struct coroutine_traits<void, T...>
    {
        struct promise_type
        {
            void get_return_object() {}

            void set_exception(exception_ptr const&) noexcept {}

            bool initial_suspend() noexcept
            {
                return false;
            }

            bool final_suspend() noexcept
            {
                return false;
            }

            void return_void() noexcept {}
        };
    };
}
Run Code Online (Sandbox Code Playgroud)

这允许您的示例进行编译。

但是,请注意,在您的示例中,调用co_await suspend_always{};会导致内存泄漏,这是因为coroutine_handle它很像原始指针,您需要自行确保协程被销毁。

作为旁注,协程仿真库CO2然而,采取另一个决定 - 它co2::coroutine具有唯一所有权,因此调用CO2_AWAIT(suspend_always{});不会泄漏内存,它只是取消协程。