1

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

让协程返回类型 beApromise.get_return_object()返回类型 be B。根据上面提到的 P0057r5 变量gro应该有类型B(由 推导auto),并且类型的对象A应该gro在协程返回其调用者时构造(例如,使用转换运算符 in或in的B隐式构造函数)。BA

在当前的 Visual Studio 实现中(编译器版本字符串:“Microsoft (R) C/C++ Optimizing Compiler Version 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
4

1 回答 1

2

在 p0057r5 中添加了捕获get_return_object()by 的返回值。auto gro在之前的版本 (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_-object() 获得返回值。对 get_return_object 的调用在调用 initial_suspend 之前排序,并且最多调用一次。

VS2015 显然实现了本文的旧版本。

于 2016-10-19T15:50:54.690 回答