为什么VS2017的协同程序无效?

时间:2017-04-06 04:04:36

标签: c++ visual-studio visual-studio-2017 coroutine

我正在使用目前在VS2017中实验的c ++协同例程进行一些实验。我只是希望有一个不会返回任何东西的协同例程,而是在一些常规对象上调用co_await,让我们说,在恢复之前对另一个线程进行一些处理。但是,VS甚至不会编译返回无效的最基本的常规程序。例如:

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

using namespace std::experimental;

void bob()
{
    co_await suspend_always{};
}

int main()
{
    bob();
}

会导致错误:

  

1&gt; c:\ program files(x86)\ microsoft visual   工作室\ 2017年\专业\ VC \工具\ MSVC \ 14.10.25017 \包括\实验\可恢复(46):   错误C2825:&#39; _Ret&#39;:后面跟着必须是类或命名空间   &#39; ::&#39; 1&gt; d:\ dev \ coroutinestest \ main.cpp(10):注意:请参阅参考   类模板实例化   &#39;的std ::实验:: coroutine_traits&#39;被编译   1&gt; c:\ program files(x86)\ microsoft visual   工作室\ 2017年\专业\ VC \工具\ MSVC \ 14.10.25017 \包括\实验\可恢复(46):   错误C2510:&#39; _Ret&#39 ;:左边的&#39; ::&#39;必须是类/结构/联合   1&gt; c:\ program files(x86)\ microsoft visual   工作室\ 2017 \专业\ VC \工具\ MSVC \ 14.10.25017 \包括\实验\可恢复(46):   错误C2061:语法错误:标识符&#39; promise_type&#39; 1以及c:\程序   files(x86)\ microsoft visual   工作室\ 2017年\专业\ VC \工具\ MSVC \ 14.10.25017 \包括\实验\可恢复(46):   错误C2238:&#39;;&#39;

之前的意外令牌

现在我假设这个错误是由于void :: promise_type是荒谬的,但是为什么承诺类型甚至在没有任何东西返回时被实例化?我希望能够从一个共同的例程中返回任何东西。这只是实施中的当前错误还是我误解了协同例程的使用。

由于

2 个答案:

答案 0 :(得分:3)

当然它可以返回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 {}
        };
    };
}

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

但请注意,在您的示例中,调用co_await suspend_always{};会导致内存泄漏,这是因为coroutine_handle非常像原始指针,并且您可以自己确保协程获得破坏。

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

答案 1 :(得分:0)

在尝试调试编译器错误消息时,我偶然发现了这个问题。对我来说,解决方案是使函数返回IAsyncAction而不是返回void