9

I have a vector of class pointers std::vector<Square*> listSquares. I want to sort it with one of the attributes of the class as the key. This is what I'm doing

bool compById(Square* a, Square* b)
{
    return a->getId() < b->getId();
}

std::sort(listSquares.begin(), listSquares.end(), compById)

but the compiler says: error: no matching function for call to 'sort(std::vector::iterator, std::vector::iterator, <unresolved overloaded function type>)'

what am I doing wrong here?

qutab
  • 307
  • 1
  • 5
  • 16

3 Answers3

13

In order to use compById as a parameter to std::sort it should not be a member function. This is wrong

class Square
{
    bool compById(Square* a, Square* b)
    {
        return a->getId() < b->getId();
    }
    ...
};

This is better,

class Square
{
    ...
};

bool compById(Square* a, Square* b)
{
    return a->getId() < b->getId();
}
john
  • 85,011
  • 4
  • 57
  • 81
  • Thank you so much. This was the problem. But why can't we declare it as a member function? Actually I'm using it in a different class than square itself. – qutab May 03 '13 at 20:47
  • 2
    Because how would std::sort know which object to use when it calls the member function? Member functions can only be called on objects, but std::sort has no context to determine which object that should be. Presumably you are calling std::sort from inside some object, but you aren't passing that object to std::sort. std::sort knows nothing about where it's being called from, all it knows are the three parameters you pass to it. – john May 03 '13 at 20:49
  • 2
    It can be a static member function. A normal (non-static) member function takes an implicit first argument, a.k.a 'this', and hence has a different signature than a non-member function. – Isac Casapu Jul 28 '16 at 09:41
3

The most important part you're missing is that the arguments to the compare function are const. Another is the return type. If you leave out the return type when declaring a function, the compiler will assume it returns int which is not correct in this case.

And of course the comparison function has to be in scope when you call the std::sort function.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • Even if I use const, I get the same error. In this case I also get, gameplay.cpp:911: error: passing 'const Square' as 'this' argument of 'int Square::getId()' discards qualifiers [-fpermissive] – qutab May 03 '13 at 20:36
  • 1
    @qutab, you have to make getId() a const member function, too. – richselian May 03 '13 at 20:43
2

You can use a member function. But you need to define it as a static member function and call it from the class, not an instance of the class.

Notice static before the function declaration, and Square:: before the function name in sort.

class Square
{
    /*...*/
public:
    static bool compById(const Square* a, const Square* b)
    {
        return a->getId() < b->getId();
    }
};

main()
{
    /*...*/
    std::sort(listSquares.begin(), listSquares.end(), Square::compById);
}
Lord Wolfenstein
  • 261
  • 2
  • 14