英文:
Are coroutine lambda arguments forwarded to the promise type's constructor?
问题
It appears that when you use a lambda to create a coroutine, the lambda's arguments are not automatically forwarded to the promise type constructor. This is why you're getting the error that the promise type constructor is being called with no arguments.
In contrast, when you declare the coroutine function directly (as in your first example), the arguments are correctly passed to the promise type constructor.
To resolve this issue, you can manually forward the Scheduler
argument to the promise type constructor within the lambda:
int main() {
Scheduler s;
auto procedure = [&s](Scheduler&) -> ReturnObject { co_return; };
auto p = procedure(s);
return 0;
}
By capturing s
by reference in the lambda [&s]
, you ensure that it is accessible within the lambda and can be forwarded to the promise type constructor as needed. This should eliminate the error you were encountering.
英文:
I'm writing an application where coroutines are executed by a scheduler. The scheduler includes a stack and some other functionality which is required for the coroutines to run properly; it doesn't make sense to have a coroutine which doesn't have access to the scheduler. I decided to make the scheduler a parameter of the promise type constructor so that whenever a coroutine is created, the promise registers it with the scheduler. Here's a simplification of my code:
#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() {}
};
With these definitions, I can declare a coroutine and use it as follows:
ReturnObject procedure(Scheduler &) {
co_return;
}
int main() {
Scheduler s;
auto p = procedure(s);
return 0;
}
The above compiles and runs without issue. However, if I replace the function with an equivalent lambda:
int main() {
Scheduler s;
auto procedure = [](Scheduler &) -> ReturnObject { co_return; };
auto p = procedure(s);
return 0;
}
I get this error:
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
Why is this? The error indicates that the promise type constructor is being called with no arguments. However, I believe that the lambda's arguments should be forwarded to the promise type constructor as the function's are.
答案1
得分: 0
lambda不等效,因为它的operator()
是非静态成员函数。尝试使用参数列表构造promise,包括隐式对象参数;错误来自于在重载解析失败时尝试进行默认构造。
注意,将lambda转换为函数指针并不会有帮助:它只是为您创建一个默认初始化的闭包对象。在C++23中,您可以声明lambda为static
以使其真正等效。
英文:
The lambda is not equivalent because its operator()
is a non-static member function. An attempt is made to construct the promise from the argument list augmented with the implicit object argument; the error comes from attempting to default-construct it when that overload resolution fails.
Note that converting the lambda to a function pointer will not help: it just creates a default-initialized closure object for you. In C++23, you can declare a lambda static
to make it truly equivalent.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论