协程 lambda 参数是否转发到 Promise 类型的构造函数?

问题描述 投票:0回答:2

我正在编写一个应用程序,其中协程由调度程序执行。调度程序包括堆栈和协程正常运行所需的一些其他功能;拥有无法访问调度程序的协程是没有意义的。我决定将调度程序作为 Promise 类型构造函数的参数,以便每当创建协程时,Promise 都会将其注册到调度程序。这是我的代码的简化:

#include <coroutine>

struct Scheduler {};

struct ReturnObject {
    
    struct promise_type;
    
};

struct ReturnObject::promise_type {
    
    promise_type(Scheduler &s) {
        // Register coroutine handle with s
    }
    
    ReturnObject get_return_object() {
        return {};
    }
    
    std::suspend_always initial_suspend() noexcept {
        return {};
    }
    
    std::suspend_always final_suspend() noexcept {
        return {};
    }
    
    void return_void() {}
    void unhandled_exception() {}
    
};

有了这些定义,我可以声明一个协程并按如下方式使用它:

ReturnObject procedure(Scheduler &) {
    co_return;
}

int main() {
    Scheduler s;
    auto p = procedure(s);
    return 0;
}

以上编译并运行没有问题。但是,如果我用等效的 lambda 替换该函数:

int main() {
    Scheduler s;
    auto procedure = [](Scheduler &) -> ReturnObject { co_return; };
    auto p = procedure(s);
    return 0;
}

我收到此错误:

demo.cpp: In lambda function:
demo.cpp:36:67: error: no matching function for call to 'ReturnObject::promise_type::promise_type()'
   36 |     auto procedure = [](Scheduler &) -> ReturnObject { co_return; };
      |                                                                   ^
demo.cpp:13:5: note: candidate: 'ReturnObject::promise_type::promise_type(Scheduler&)'
   13 |     promise_type(Scheduler &s) {
      |     ^~~~~~~~~~~~
demo.cpp:13:5: note:   candidate expects 1 argument, 0 provided
demo.cpp:11:22: note: candidate: 'constexpr ReturnObject::promise_type::promise_type(const ReturnObject::promise_type&)'
   11 | struct ReturnObject::promise_type {
      |                      ^~~~~~~~~~~~
demo.cpp:11:22: note:   candidate expects 1 argument, 0 provided
demo.cpp:11:22: note: candidate: 'constexpr ReturnObject::promise_type::promise_type(ReturnObject::promise_type&&)'
demo.cpp:11:22: note:   candidate expects 1 argument, 0 provided

这是为什么呢?该错误表明正在调用不带参数的 Promise 类型构造函数。但是,我认为 lambda 的参数应该像函数一样转发到 Promise 类型构造函数。

c++ lambda coroutine
2个回答
2
投票

lambda 不等价,因为它的

operator()
是一个 非静态 成员函数。 尝试从用隐式对象参数扩充的参数列表构造承诺;该错误来自于在重载解析失败时尝试默认构造它。

请注意,将 lambda 转换为函数指针不会有帮助:它只是为您创建一个默认初始化的闭包对象。 在 C++23 中,您可以声明 lambda

static
以使其真正等效。


0
投票

在 C++20 中,您还可以重载

promise_type
的构造函数作为解决方法:

struct ReturnObject::promise_type {
    promise_type(Scheduler &s) {
        // Register coroutine handle with s
    }
    // workaround for non-static lambdas (ignore implicit this argument)
    promise_type([[maybe_unused]] auto &IgnoreMe, Scheduler &s) : promise_type(s) {
    }
    // ...
};

这是编译器资源管理器中的一个工作示例。

© www.soinside.com 2019 - 2024. All rights reserved.