Search code examples
c++operator-overloadingpriority-queue

Operator overloading on priority_queue of object pointers


class MyInteger
{
public:
    MyInteger() { }
    MyInteger(int val) { value = val }

    int value;

    bool operator<(const MyInteger* target) const
    {
        return value < target->value;
    }

Above is an example MyInteger class with the < operator overloaded. I am using a priority_queue of MyInteger*but it doesn't seem to recognize the overloaded operator, which results in the elements never being ordered.

std::priority_queue<MyInteger*> myInts;

MyInteger integer1 = MyInteger(1);
MyInteger integer5 = MyInteger(5);
MyInteger integer3 = MyInteger(3);

myInts.push(&integer1);
myInts.push(&integer5);
myInts.push(&integer3);

// result is same order they went in

Is it possible to use operator overloading for object pointers? Does it mean I will have to create my own functor to be used instead?


Solution

  • As mentioned by Olaf Dietsche, as you store pointers, the objet adresses are used for sorting, so in most case, order in the container will be equal to order of creation.

    You'd better store objects in the container. Then it's comparison operator will be used for ordering:

    class MyInteger
    {
    public:
        MyInteger() { }
        MyInteger(int val) { value = val }
        MyInteger( const MyInteger& val ) : value( val.value ) {}
    
        int value;
    
        bool operator<(const MyInteger& target) const
        {
            return value < target.value;
        }
    
    };
    
    ...
    
    std::priority_queue<MyInteger> myInts;
    
    MyInteger integer1 = MyInteger(1);
    MyInteger integer5 = MyInteger(5);
    MyInteger integer3 = MyInteger(3);
    
    myInts.push(integer1);
    myInts.push(integer5);
    myInts.push(integer3);
    

    Then objects will be ordered correctly (using operator<).

    It is even safer in case integer1, integer2 or integer3 gets destroyed before myInts (as this one stores copies).

    If you really need to save pointers, then you 'ill have to pass a custom comparator to the container. See declaring a priority_queue in c++ with a custom comparator.

    This should work:

    class CompareMyIntegerPtr
    {
    public:
        bool operator() (MyInteger* left, MyInteger* right)
        {
            return left->value < right->value;
        }
    };
    
    ...
    
    std::priority_queue<MyInteger*, std::vector<MyInteger*>, CompareMyIntegerPtr> myInts;