是否可以在lambda代码本身之外访问lambda的捕获值。
template <typename F>
void bar(const F& f)
{
auto d = f.x;
}
int main()
{
int x;
bar([&]{
do_something(x);
});
}
答案 0 :(得分:2)
这是不可能的。 Lambda是一个黑匣子。
如果只需要一个捕获的变量,并且如果lambda最初应该为空,则只需返回此值。
template <typename F>
void bar(const F& f)
{
auto d = f();
}
int main()
{
int x;
bar([&]{
auto y=x; // in case do_something would change x
do_something(x);
return y;
});
}
如果您已经需要返回值,则可以使用sam方法,但可以使用一对或元组一次返回多个值:
template <typename F>
void bar(const F& f)
{
auto d = f();
cout << d.first<<endl;
}
int main()
{
int x;
bar([&]{
auto y=x;
do_something(x);
return make_pair(y, 0); // first is parameter, second real return
});
}
嗯,它不再是lambda了。但是,如果您需要访问一些更复杂的函数的参数,则可以使用可调用对象。可调用的是普通的类或结构。然后,它可以传达您想要的任何参数,但是您需要定义它们并在可调用对象的构造函数中预见它们:
template <typename F>
void bar(const F& f)
{
auto d = f.x;
f();
}
int main()
{
struct Tmp { // I won't need this callable elsewhere...
int &x;
Tmp (int& x) : x(x) {}
void operator() () const {
do_something(x);
}
};
int x;
Tmp t(x);
bar(t);
}
在此示例中,我使用了一个本地类定义,以免用扔掉的结构污染名称空间。
您可以通过将lambda作为构造函数的参数来提供此方法与lambda结合,捕获大量变量,并使用可调用成员来传达您只能在bar()
中使用的少数几个。
请注意按引用捕获(当捕获的变量可能已死亡时,请不要使用lambda。
如果需要访问lambda的命名参数,则设计中可能存在问题。 Lambda不能传递捕获的变量。因此,如果您有此需要,有可能可赎回债券是一个更好的选择。
答案 1 :(得分:0)
是否可以在lambda代码本身之外访问lambda的捕获值
是的,是的,但是不是通过lambda的:不是通过某种方式公开[&]
lambda捕获的所有本地名称听起来很讨厌。
这些变量在绑定到lambda之前已经具有名称,您仍然可以照常使用这些名称。
编写具有自己的名称和语义的函子是获得所需行为的唯一方法。如果您不想显式命名每个捕获的变量,则可以使用带有std::apply
的元组(以及常规的元组字段访问)。