VS2015 C ++协同程序:promise.get_return_object()返回类型和协程返回类型

时间:2016-10-18 21:08:52

标签: c++ visual-c++ c++-coroutine

我对Coroutines TS的Visual Studio 2015实施有疑问。 P0057r5工作文件指出协程的行为就像它的身体一样:

{
    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推导类型的变量中。

让coroutine返回类型为Apromise.get_return_object()返回类型为B。根据上面提到的P0057r5,变量gro应该具有类型B(由auto推导),当协程返回时,A类型的对象应该从gro构造其调用者(例如,使用B中的转化运算符或BA的隐式构造函数)。

在当前的Visual Studio实现中(编译器版本字符串:“Microsoft(R)C / C ++优化编译器版本19.00.24215.1 for x86”)转换在p.initial_suspend()之后和F'被调用之前完成如果gro类型设置为匹配协程的返回类型(A)而不是promise.get_return_object()B)的返回类型。

我错过了什么或这是一个错误吗?

最小示例(使用/ await编译):

#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();
}

输出:

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

1 个答案:

答案 0 :(得分:2)

Capturing return value of get_return_object() by auto gro was added in p0057r5. In previous revision (p0057r4) this part reads as

...the coroutine behaves as if its body were:

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

and

When a coroutine returns to its caller, the return value is obtained by a call to p.get_return_- object(). A call to a get_return_object is sequenced before the call to initial_suspend and is invoked at most once.

VS2015 obviously implements older version of this paper.