2017-04-06 95 views
2

我正在做一些实验,提出了目前在VS2017中实验的C++协同例程。我只是想有一个协同例程,它不会返回任何东西,而是调用某个co-routine对象的co_await,比方说,在恢复之前在另一个线程上执行一些处理。然而,VS甚至不会编译即使是最基本的协同例程程序,它将返回无效。例如:为什么VS2017协程无法返回无效?

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

using namespace std::experimental; 

void bob() 
{ 
    co_await suspend_always{}; 
} 

int main() 
{ 
    bob(); 
} 

导致错误:

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 namespace when followed by '::' 1>d:\dev\coroutinestest\main.cpp(10): note: see reference to class template instantiation 'std::experimental::coroutine_traits' being compiled 1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.10.25017\include\experimental\resumable(46): error C2510: '_Ret': left of '::' must be a class/struct/union 1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.10.25017\include\experimental\resumable(46): error C2061: syntax error: identifier 'promise_type' 1>c:\program files (x86)\microsoft visual studio\2017\professional\vc\tools\msvc\14.10.25017\include\experimental\resumable(46): error C2238: unexpected token(s) preceding ';'

现在我认为这个错误是由于无效:: promise_type是荒谬的,但为什么许型甚至被当没有什么实例回来?我希望能够从协同例程中不做任何回报。这只是实现中的一个当前错误,还是我误解了使用协同例程。

谢谢

+0

协程式返回期货。在这种情况下,'std :: future '。 –

+0

感谢您的回复。我已经阅读过的所有会谈/文档显示协程返回任何你希望的非空类型(假设它满足一些基本标准)。但是他们没有明确说明为什么void对协程无效。我可以完全想象一个处理作业的协同程序(使用co_await将工作放在工作队列中)以及何时返回,而不想返回值。 正如你所建议的,虽然我可能会诉诸未来或其他虚拟类型作为解决方法,但这看起来像这样,最好的解决方法,最坏的错误。 – AKB

+0

你指的是什么谈话/文件? MS对C++协程的实现(以及目前在协程TS中的措辞)**要求**协程的返回类型来公开'promise_type'。你可以实现你自己的'future'类型,或者简单地使用'std :: future',但你绝对不能简单地返回'void'。这既不是解决方法或错误,也是MS协程的指定方式。也许你正在考虑一个不同的协程(C Kohloff的协议),它确实不需要在期货中包装返回类型。 –

回答

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{});,呼叫不会泄漏内存,它只是取消协程。