Reputation: 2426
Writing compare functions for STL algorithms & containers is tedious.
For simple objects such as this,
struct Person
{
int id;
string name;
string surname;
string get_full_name(); // name then surname
};
I have to type the same function call for both lhs
and rhs
:
vector<Person> v = { ... };
std::sort( v.begin(), v.end(), [](const Object &lhs, const Object &rhs) {
return lhs.get_full_name() < rhs.get_full_name(); // tedious
} );
I would like to be able to compose a compare function/functor using a pointer-to-member-function or pointer-to-member-data. Maybe like so:
std::sort( v.begin(), v.end(), make_compare_functor( &Object::get_full_name ));
std::sort( v.begin(), v.end(), make_compare_functor( &Object::surname ));
I've tried to implement it like so:
template <class R, class T>
struct CompareFunctor {
R (T::*fp)();
bool operator() (const T& lhs, const T& rhs) {
return lhs->*fp() < rhs->*fp();
}
};
// helper function
template <class R, class T>
CompareFunctor<R,T> make_compare_functor(R(T::*fp)()) {
return CompareFunctor<R,T> { fp };
}
but it fails to instantiate T
for any of these cases
auto functor1 = make_compare_functor( &Person::get_full_name );
auto functor2 = make_compare_functor( &std::string::size );
(the error message is like: 'make_compare_functor': no matching overloaded function found ... note: could be 'const Person' or 'Person'
)
can anybody guide me how to to compose a compare function/functor using a pointer-to-member-function please?
It should preferably be STL based -- no Boost or another library.
Upvotes: 0
Views: 68
Reputation: 60208
You're on the right track, but you'll need to overload make_compare_functor
to accept both a pointer-to-member-function, as well as a pointer-to-member. In addition, you'll need to write a CompareMember
that compares pointer-to-members, similar to how CompareFunctor
compares pointer-to-member-functions:
// compare pointer to member function
template <class R, class T>
struct CompareFunctor {
R (T::*fp)() const;
bool operator() (const T& lhs, const T& rhs) {
return (lhs.*fp)() < (rhs.*fp)();
}
};
// compare pointer to member
template <class T, class M>
struct CompareMember {
M T::*mp;
bool operator() (const T& lhs, const T& rhs) {
return lhs.*mp < rhs.*mp;
}
};
// helper function : compare pointer to member function
template <class R, class T>
CompareFunctor<R,T> make_compare_functor(R(T::*fp)() const) {
return CompareFunctor<R,T> { fp };
}
// helper function : compare pointer to member
template <class T, class M>
CompareMember<T, M> make_compare_functor(M T::*mp) {
return CompareMember<T, M> { mp };
}
Here's a demo.
Note that I added const
to the pointer-to-member-function signatures, and corrected a couple of typos in the question's code.
Also make_compare_functor
should probably be renamed to make_compare
now that it accepts pointer-to-members as well.
Upvotes: 1