2016-10-18 24 views
1

Visual Studio 2015のCoroutines TS実装に関する質問があります。 P0057r5ワーキングペーパーは、コルーチンは、その本体であるかのように振る舞うことを示す:VS2015 C++コルーチン:promise.get_return_object()戻り値の型とコルーチン戻り値の型

{ 
    P p; 
    auto gro = p.get_return_object(); 
    co_await p.initial_suspend(); // initial suspend point 
    F’ 
final_suspend: 
    co_await p.final_suspend(); // final suspend point 
} 

(8.4.4 \ 3条) 、その呼び出し元にコルーチンリターンが、戻り値はによってかのように生成された場合にステートメントreturn gro;(§8.4.4\ 5)

p.get_return_object()の結果は、autoの推論型の変数に格納されます。

コルーチンの戻り値の型をAおよびpromise.get_return_object()の戻り値の型をBとします。可変gro上記P0057r5によれば、(autoによって推定)タイプBを有するべきであり、コルーチンは、(例えば、ABからBまたは暗黙的なコンストラクタで変換演算子を使用して)、その呼び出し元に戻るときタイプAの目的はgroから構成されるべきです。

現在のVisual Studioの実装(コンパイラのバージョン文字列:「x86用のMicrosoft(R)C/C++最適化コンパイラバージョン19.00.24215.1」)で変換がp.initial_suspend()後に行われるとF'gro型が一致するように設定されたかのように呼び出されますコルーチンの戻り値の型(A)で、戻り値の型はpromise.get_return_object()B)ではありません。

私に何かが見つからないか、これはバグですか?

最小例(/待機してコンパイル):

#include <experimental/coroutine> 
#include <iostream> 

struct foo; 
struct foo_builder { 
    foo_builder() { 
     std::cout << "foo_builder constructor\n"; 
    } 
    operator foo(); 
}; 

struct foo_promise { 
    foo_builder get_return_object() { 
     return{}; 
    } 
    void return_value(int value) { 
     std::cout << "co_return with " << value << "\n"; 
    } 
    std::experimental::suspend_never initial_suspend() { 
     std::cout << "Initial suspend\n"; 
     return{}; 
    } 
    std::experimental::suspend_never final_suspend() { 
     return{}; 
    } 
}; 

struct foo { 
    foo() { 
     std::cout << "foo constructor\n"; 
    } 
    using promise_type = foo_promise; 
}; 

foo_builder::operator foo() { 
    std::cout << "foo_builder conversion to foo\n"; 
    return{}; 
} 

foo coroutine() { 
    co_return 5; 
} 

foo simple() { 
    foo_promise p; 
    auto gro = p.get_return_object(); 
    // co_await p.initial_suspend(); // initial suspend point 

    // co_return 5; 
    p.return_value(5); //S; 
    goto final_suspend; 

final_suspend: 
    // co_await p.final_suspend(); // final suspend point 
    return gro; 
} 


int main() { 
    auto v = coroutine(); 

    std::cout << "\nregular function:\n"; 

    auto v2 = simple(); 

    std::cin.ignore(); 
} 

出力:auto groによってget_return_object()の戻り値をキャプチャ

Initial suspend 
foo_builder constructor 
foo_builder conversion to foo 
foo constructor 
co_return with 5 

regular function: 
foo_builder constructor 
co_return with 5 
foo_builder conversion to foo 
foo constructor 

答えて

2

はp0057r5で添加しました。この部分は

として読み出し以前のリビジョン(p0057r4)にその本体であるかのよう...コルーチンは振る舞う:

{ 
    P p ; 
    co_await p .initial_suspend(); // initial suspend point 
    F’ 
final_suspend : 
    co_await p .final_suspend(); // final suspend point 
} 

コルーチン戻るへの戻り値は、p.get_return_- オブジェクト()の呼び出しによって取得されます。 initial_suspendの呼び出しの前にget_return_objectの呼び出しがシーケンスされ、最大でも が呼び出されます。

VS2015は明らかにこのペーパーの古いバージョンを実装しています。