是否可以访问(只读)lambda捕获的变量?
这不起作用:
std::function<double (const double)> plus (const double a) {
return [a] (const double b) -> double {
return a+b;
};
}
auto plus5 = plus(5);
cout << plus5.a << endl;
Run Code Online (Sandbox Code Playgroud)
Yak*_*ont 16
auto plus( double a ) {
using R = struct {
double a;
double operator()(double b)const{return b+a;}
};
return R{std::move(a)};
}
Run Code Online (Sandbox Code Playgroud)
实例.
请注意,a std::function不是lambda,而lambda不是lambda std::function.他们互相合作,但使用一个术语来指向另一个是有用的.
Com*_*sMS 14
这不是lambda应该如何使用.
lambda的接口是它的函数签名.其捕获应被视为实现细节,并且对用户不可见.
如果要显式访问捕获,请编写自己的函数对象并相应地公开相应的数据成员:
struct MyPlus {
double a;
MyPlus(double x) : a(x) {}
double operator()(const double b)
{
return a+b;
}
};
auto plus5 = MyPlus(5);
std::cout << plus5.a;
Run Code Online (Sandbox Code Playgroud)
"绝对不是在将它存储在std函数之后.没有它,我可以用C++ 17中的一个可怕的(但合法的)黑客来做.但是我会是一个可怕的人告诉你如何,因为你可能会使用它. " - Yakk
好吧,让我们减轻Yakk的业力; 这里是C++ 14解决方案的概念证明,你绝对不想放弃它:
auto magic = [a, b](auto &&... args) mutable -> decltype(auto) {
return makeOverload(
// Capture access boilerplate
[&](cap_<0>) -> auto& { return a; },
[&](cap_<1>) -> auto& { return b; },
// Actual function
[&](int p) {
return "[" + std::to_string(a) + ", " + b + "](" + std::to_string(p) + ")";
}
)(std::forward<decltype(args)>(args)...);
};
Run Code Online (Sandbox Code Playgroud)
makeOverload采用任意数量的仿函数并将它们合并为一个仿函数.我从这篇博文中借用了这个想法,并在评论部分的帮助下使其真正起作用.
生成的仿函数用于在cap<N>标记和函数的实际参数之间进行标记分派.因此,调用magic(cap<0>)会导致它吐出相应的捕获变量,即a.当然,函数的实际行为仍然可以通过正常调用来访问magic(123).
作为奖励,外部lambda是mutable,并且捕获访问器通过引用返回:您实际上对捕获的变量具有读写访问权限!
您可以在这里的 Coliru自然栖息地观察并与这种生物互动.