[英]C++ how to convert member functions to standalone functions (for use as function parameter) generically?
对于模板函数的函数参数,我发现自己经常将成员函数包装在lambda中以创建相同的独立函数,第一个参数是对象。
一个(虚拟)示例:
class A
{
public:
double f1() const;
double f2(int i) const;
// some data
};
template <typename Func>
double calculateSum(std::vector<A> as, Func f)
{
double result = 0.0;
for (auto a : as)
result += f(a);
return result;
}
int main()
{
std::vector<A> as;
int i = 0;
auto sum1 = calculateSum(as, [](const A& a) { return a.f1(); });
auto sum2 = calculateSum(as, [&i](const A& a) { return a.f2(i); });
return 0;
}
有没有办法更一般地定义这样的lambdas? 或者有没有办法直接引用成员函数而不是使用lambdas?
您可以使用C ++ 14通用lambdas来帮助解决这个问题。 像这样定义你的通用lambda:
auto bindMem = [](auto f, auto& ... memArgs) { return [f, &memArgs...](auto& a) { return (a.*f)(memArgs...); }; };
要消化:这会创建一个通用的lambda,其调用会产生另一个lambda。 第一拉姆达让你要调用的成员函数,与任何绑定参数(比其他this
对象)。 它生成第二个lambda,然后它就会期望对象本身并使用先前绑定的参数对其应用成员函数调用。
因此,对于您的用例,您看起来很整洁:
auto sum1 = calculateSum(as, bindMem(&A::f1));
auto sum2 = calculateSum(as, bindMem(&A::f2,i));
关于这一点的bindMem
是,完全相同的bindMem
lambda将适用于任何类和任何成员函数,具有任意参数列表。 因此,你的意思是它真的是通用的。
你可以使用std::bind()
。
绑定需要一个函数,无论你想要多少参数,都会返回一个很好的std::function
对象。 您可以在创建时指定参数,也可以在调用返回的函数时使用占位符指定它们。
#include <functional>
...
auto sum1 = calculateSum(as, std::bind(&A::f1, std::placeholders::_1));
auto sum2 = calculateSum(as, std::bind(&A::f2, std::placeholders::_1, i);
请记住,非静态成员函数将类实例作为它们的第一个参数(尽管大多数情况下它是隐式完成的,但这不是其中之一),这就是我们使用占位符的原因。 当你现在执行f(a)
时, a
(类实例)将替换该占位符。
经过一番研究,感谢@happydave的建议,我将回答以下问题:
auto sum1 = calculateSum(as, std::mem_fn(&A::f1));
第二笔金额不能这样处理,应该保持为lambda。 但是,一般来说,似乎客户端代码是参数的供应商的可能性较小(在这种情况下,参数需要以任何方式传递给模板函数(并且lambda捕获是一种很好的方式))。 在许多情况下,模板函数也提供传递函数的参数,std :: mem_fn也没问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.