我正在使用目前在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是荒谬的,但是为什么承诺类型甚至在没有任何东西返回时被实例化?我希望能够从一个共同的例程中返回任何东西。这只是实施中的当前错误还是我误解了协同例程的使用。
由于
答案 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
。