Link to home
Start Free TrialLog in
Avatar of iyac
iyacFlag for Canada

asked on

Specifying a comparison function for a multiset

I was trying to specify an overloaded greater-than operator as a second parameter to an instantiation of a multiset.  I was expecting that I could specify MyClass::operator> but the compiler didn't like this.  Using greater<MyClass> worked.  This looks somewhat like a function template to me but I still don't understand why I had to use that instead of something that looked very much like the overloaded operator definition syntax (MyClass::operator>).  Can someone explain to me why I had to use the one and not the other?
Avatar of phoffric
phoffric

If you could you post the code that does not compile in the Code box, that will provide a good starting point. Likewise (maybe as a separate post to keep them apart) could you post the code that does compile and work correctly.
Overloading the comparison operators
http://www.learncpp.com/cpp-tutorial/94-overloading-the-comparison-operators/

Probably you forgot to make this operator "friend":
friend bool operator>(const MyClass& x, const MyClass& y);
>> I was expecting that I could specify MyClass::operator> but the compiler didn't like this
You can't specify a predicate that is a class instance function. You need to provide a predicate functor. Below is a simple functor that implements lessThat (the formal predicate) for a multiset if int types. Use that as an example and modify to suit your needs.

http://www.cplusplus.com/reference/stl/multiset/
#include <set>

struct functor
{
   bool operator()(int lhs, int rhs) const // Change these types to suit
   {
      return (lhs < rhs); // Change this logic to suit
   }
};

int main()
{
   std::multiset<int, functor> mset;
}

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
To add to above comments:

As mentioned from evilrix the second argument of multiset requires a "less-than" and not a "greater-than" compare function beside you want to sort in descending order. But if so, you shouldn't turn the functionality in operator< but provide a global (or static member) compare function for the multiset in order to not spoiling 'normal' comparisions.

Note, the functor evilrix showed above is a wonderful means to have a comparision which either sorts ascending or descending by simply adding a member to the functor class as sortmode:

class myfunctor
{
   bool ascending;
public:
   myfunctor() : ascending(true) {}
   myfunctor(bool asc_or_desc) : ascending(asc_or_desc) {}
   bool operator()(const myclass & lhs, const myclass & rhs) const
   {
        return ascending? (lhs < rhs) : (rhs < lhs);
   }
};

 // sort descending
 std::multiset<int, myfunctor(false) > mset;

 
>> As mentioned from evilrix the second argument of multiset requires a "less-than" and not a "greater-than" compare
Actually, that's not what I said :) I said (probably not very clearly knowing me) it will call operator <() on the class if a sort predicate functor isn't provided.

Just to note, the functor is generally a less-than but it can be any predicate. For example, if you provide a greater-than it'll order in descending rather than ascending order. What I said is that it's a functor. The important thing is the behaviour is consistent so as to facilitate consistant key ordering.
Note that the functor shown by evilrix in http:#29310788 is basically the same is the standard less functor :

        http://www.cplusplus.com/reference/std/functional/less/

which is similar to the standard greater functor you were already using :

        http://www.cplusplus.com/reference/std/functional/greater/

I'd suggest to simply keep using the standard functors, unless you need different functionality ;)


Note also that the standard <functor> library provides functors for the other operators too - they come in very handy !
>> the standard <functor> library

typo there ... make that <functional> instead ;)
>> Note that the functor shown by evilrix in http:#29310788 is basically the same is the standard less functor :
Agreed, but it was a coded example in case iyac wished to implement different logic to that of the standard less and greater predicates.

>> I'd suggest to simply keep using the standard functors, unless you need different functionalit
Agreed.