Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding multiple arguments to member functions in C++

Say I have class A with member function int f() { return m_; } where m_ is a data member. I have a vector<A> called vec, and I want to find the object with maximum m_ value in vec using std::max_element. I can do it with a lambda:

auto cmp = [] (A& x, A& y) { return x.f() < y.f(); };
A& max_elem = *std::max_element(vec.begin(), vec.end(), cmp);

Is there some bind (or some such) trickery that will allow me to do it without a lambda and without defining my own comparator from scratch? Please don't suggest better ways to solve the max finding problem. It's only an example. The general question is how to wrap a function object that takes more than one argument (e.g., std::less<int>, which I would use as the comparator in the above example) in such a way that that arguments sent to it go through some other function (or member function) before getting to it.

like image 795
Ari Avatar asked Feb 19 '14 10:02

Ari


1 Answers

Yes, there is:

using namespace std::placeholders;
A& max = *std::max_element(begin(vec), end(vec)
    , std::bind(
        &std::less<int>::operator()
        , std::less<int>()
        , std::bind(&A::f, _1)
        , std::bind(&A::f, _2)
    )
);

Live example

However, if I ever saw this in code review, I'd immediately say "turn that ugliness into a lambda."


Thanks to @n.m. for poining out that the code can be shortened a bit:

using namespace std::placeholders;
A& max = *std::max_element(begin(vec), end(vec)
    , std::bind(
        std::less<int>()
        , std::bind(&A::f, _1)
        , std::bind(&A::f, _2)
    )
);

Live example

I still consider a lambda more readable, though. Bear in mind that you can use a lambda directly in the call to max_element() (no need for the variable cmp in your original code).

like image 66
Angew is no longer proud of SO Avatar answered Oct 18 '22 05:10

Angew is no longer proud of SO