在我的代码中,我现在有类似的东西
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
[&bar](Foo const &lhs, Foo const &rhs) {
return bar.myWeakLessOperator(lhs, rhs);
});
我想知道是否存在一种通过直接传递成员函数myWeakLessOperator
(不是静态的)而不是编写用于调用的lambda函数来简化它的方法。
我想获得类似的东西
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
/* something that rely to */ bar.myWeakLessOperator);
有没有可能的想法以及如何做到?
答案 0 :(得分:2)
因此,您需要一个函数对象,该对象表示绑定到特定接收者的成员函数。不幸的是,我在标准或Boost中找不到能做到这一点的东西。
您所能做的就是相当轻松地编写自己的内容。
template <typename R, typename T>
struct member_function_binder {
T *receiver;
R T::*pmf;
template <typename... Args>
auto operator()(Args&&... args) {
return (receiver->*pmf)(std::forward<Args>(args)...);
}
};
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return member_function_binder<R, T>{&receiver, pmf};
}
看看live demo,我想这可能就是您想要的。
更简洁的是,如果您像这样从member_function_binder
返回一个lambda,则不需要单独的类bind_member_function
:
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return [pmf, &receiver](auto&&... args) {
return (receiver.*pmf)(std::forward<decltype(args)>(args)...);
};
}
传递像Foo::compareTo(const Foo &rhs)
这样的一元成员函数而不是OP要求的解决方案:
您想要的是std::mem_fn
;它是使成员函数指针变成函数对象的包装器。您将这样使用它:
auto min = std::min_element(
begin(mySet), end(mySet), std::mem_fn(&Foo::myWeakLessOperator));
答案 1 :(得分:2)
一种可能的解决方案是在Foo中使用满足Compare的结构:
class Foo
{
public:
struct WeakLessOperator
{
bool operator()(const Foo& a, const Foo& b)
{
// implementation - take care of meeting requirements of Compare
return true;
}
};
WeakLessOperator myWeakLessOperator;
};
Foo bar;
auto minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
bar.myWeakLessOperator);
答案 2 :(得分:1)
您可以使用std::bind
或其他wrapper。
示例:
using namespace std::placeholders;
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
std::bind(&Foo::myWeakLessOperator, bar, _1, _2));
OR
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
gnr::memfun<MEMFUN(Foo::myWeakLessOperator)>(bar));
答案 3 :(得分:0)
最接近您想要的是
auto minElement =
std::min_element(
std::begin(mySet),
std::end(mySet),
mem_fun_functor(&Foo::myWeakLessOperator)
);
有std::mem_fun
(在c ++ 11中已弃用)和std::mem_fn
都包装了一个成员函数指针,尽管两者都以实例作为参数来调用该成员函数。如果您想要一个也可以包装对象的函子,我认为您需要编写自己的函子:
auto mem_fun_functor =
[&bar](decltype(&Foo::myWeakLessOperator) f){
return [f,&bar](const Foo& a,const Foo& b) {
return (bar.*f)(a,b);
};
};
但是,鉴于所有答案都不是那么短,也不会使代码更简洁,因此,我考虑将第一个版本与lambda一起使用(除非您可能有许多要用作比较器的成员函数)
“简化”实际上是什么意思?您确实需要指定要在其上调用成员函数的对象,还需要指定要如何转发参数。那基本上就是lambda所做的所有事情。
例如,将所有这些操作都交给函子可以使您的代码更复杂而不是更简单。在您的第一个摘录中,熟悉标准算法的任何人都可以查看那几行代码,完全了解正在发生的事情。
最终这是样式问题,您认为可读性强,但是能够在最窄的范围内声明内容是使用lambda的一大优势。