2017-04-06 94 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{});,呼叫不會泄漏內存,它只是取消協程。