我想做这样的事情:
// define a lambda to be called from some class method
auto state_0_stuff = [&](){
.
caller_data.some_func(); <-- identifier undefined compiler error
.
}
// call the lambda from some class method, capturing the data and using in the lambda.
void foo::some_func(){
int state = 0;
bool done = false;
// more data...
bar caller_data;
while(!done){
switch(state){
case 0:
state_0_stuff(); <-- instead of adding lots of code here, call lambda
state = 1;
break;
case 1:
done = true;
break;
}
}
}
如果我在foo :: some_func主体中定义lambda,这将起作用,但如果我尝试在外部定义lambda,则不会。
是否有一些相对简单的语法可以达到这种效果?
我不在乎是否使用lambda,这只是我的第一个主意。目的是简化switch(state)的内容,以使代码比在情况下添加50行内容的代码更具可读性。
很明显,我可以使用正常的函数,并来回传递一堆东西,但是如果像Lambda那样仅由函数捕获本地状态,那就不会那么复杂了。
答案 0 :(得分:4)
没有任何方法可以隐式捕获Lambda中超出对象范围的对象。您需要明确地传递它们。
作为解决方案,您可以向private
添加foo
成员函数,然后调用该函数:
void foo::case0(bar& caller_data, /* ... */)
{
lots_of_calcs_that_reference_caller_data();
.
caller_data.some_func();
.
}
void foo::some_func(){
int state = 0;
bool done = false;
// more data...
bar caller_data;
while(!done){
switch(state){
case 0:
case0(caller_data, /* ... */);
state = 1;
break;
case 1:
done = true;
break;
}
}
}
否则,您可以使用重载的struct
创建一个operator()
并在其构造函数中传递“捕获”。
答案 1 :(得分:3)
lambda捕获声明状态的状态。所以当你有
auto state_0_stuff = [&](){
lots_of_calcs_that_reference_caller_data();
.
caller_data.some_func();
.
}
全局空间[&]
中的仅捕获该空间中可用的内容。当您在函数中调用lambda时,它将使用捕获的状态,而不是函数的当前状态。
您将不得不在函数中声明lambda或编写将状态传递给的函数/函数。您还可以将其设为类的私有成员函数,以便它可以访问类状态,而只需将所需的任何函数本地状态传递给它。
关于声明lambda时会发生什么的更深入的研究:
这样做的时候
auto foo = [&](){ your code here };
编译将其扩展为类似(非常简化)的内容:
struct some_compiler_generate_name
{
some_compiler_generate_name(list of captured variables) : initialize captured variables {}
operator () const { your code here }
private:
captured variables;
} foo(list of variables to capture);
因此您可以看到我们在声明时就创建了lambda对象,并且由于此操作,它会用它可能具有的所有捕获变量进行初始化。您无法重新捕获变量,因为您无法再次调用其构造函数。