2017-04-06 3 views
2

私はVS2017で現在実験中の提案されたC++コルーチンでいくつかの実験を行っていました。私は単に何も返さないコルーチンを持っていたが、再開する前に別のスレッドで何らかの処理をしているコルーチンオブジェクトをco_awaitで呼び出すだけだった。しかし、VSはvoidを返す最も初歩的なコルーチンプログラムであってもコンパイルしません。例えば:エラーでなぜVS2017コルーチンはvoidを返せませんか?

#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型を返すコルーチンを示します(いくつかの基本基準を満たしていると仮定します)。しかし、彼らはなぜコルーチンにvoidが有効でないのかを明示的に述べていない。私は仕事を処理するコルーチンを想像することができます(co_awaitを使用して作業者のキューにジョブを投入する)、それが戻ったときに値を返すことを望まない。 将来的にはや他のダミータイプに訴えるかもしれませんが、これはそのように思われますが、最高の回避策、最悪のバグです。 – AKB

+0

あなたはどんな会話/ドキュメントを参照していますか? MSのC++コルーチンの実装(そして現在コルーチンTSで言及されているように)**は、 'promise_type'を公開するコルーチンの戻り型を必要とします。あなたは 'std :: future'を使用する独自の' future'型を実装することもできますが、単純に 'void'を返すことはできません。これは回避策でもバグでもなく、MSコルーチンが指定されている方法です。おそらく、あなたは、コルーチン(C.コフロフのもの)の別の提案を考えています。実際には、先物型で戻り値の型を入れる必要はありません。 –

答えて

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{});への呼び出しは、メモリリークが発生しません、それだけでコルーチンをキャンセルします。

関連する問題