-2

After reading some answers on stackoverflow I still couldn't understand when will compare function has to return false and when will it return true. In this answer it is written that it models the less than operator but still what I think now is that if compare function is like:

bool compare(const myClass& object1, const myClass& object2)
{
     if(object1.property < object2.property)
         return true;
     else
         return false;
}

will sort a vector of myclass objects in ascending order. Am I right?...I think I'm still confused.

Prabhat Sharma
  • 76
  • 1
  • 12
  • 1
    https://en.cppreference.com/w/cpp/algorithm/sort – Tyker Jul 06 '18 at 09:08
  • This is basically fine, but a few improvements: Make parameters const reference (`const myClass&`) and function body can be one-liner: `return object1.property < object2.property;`. – zett42 Jul 06 '18 at 09:09
  • Actually here it can be one liner but my application demands some preprocessing to compare the objects according to its property and then return the result in an if-else manner....that's why I've written it like this :) Btw thanks for your suggestion. – Prabhat Sharma Jul 06 '18 at 09:11
  • The "less than" operator is sufficient to define a strict order. Eg. `a < b` is the same as `b > a`. Further, `(a < b) || (b < a)` defines `a != b`. Then `!((a < b) || (b < a))` defines `a == b`. Combine to get `<=` and `>=`, and you have full coverage from just one operator. – Sander De Dycker Jul 06 '18 at 09:20
  • Off-topic: Don't write code like `if(condition) return true; return false;` (or with else as yours), just write `return condition;`; and if you return `false` in if clause, invert condition (`return !condition;`). – Aconcagua Jul 06 '18 at 09:21
  • @Aconcagua I know but please read my above comment for my clarification :) – Prabhat Sharma Jul 06 '18 at 09:22

2 Answers2

5

When in doubt, read the reference.

comp -

comparison function object (i.e. an object that satisfies the requirements of Compare) which returns ​true if the first argument is less than (i.e. is ordered before) the second.

The signature of the comparison function should be equivalent to the following:

bool cmp(const Type1 &a, const Type2 &b);

The signature does not need to have const &, but the function object must not modify the objects passed to it. The types Type1 and Type2 must be such that an object of type RandomIt can be dereferenced and then implicitly converted to both of them. ​

Community
  • 1
  • 1
hellow
  • 12,430
  • 7
  • 56
  • 79
  • Btw I couldn't find official documentation easily on searching. Mostly reference and other sites like cpluspus.com come in handy! – Prabhat Sharma Jul 06 '18 at 09:20
2

While refering to standard is fine, understanding it can sometimes be quite hard...

Trying in simpler words:

If you want to sort elements, you need some kind of order relation that defines which of two elements shall come first ("be the smaller one"). Some data types come with a natural order, such as integral numbers, for instance: -12 < -10 - 0 - 10 < 12. std::sort (without comparison parameter) uses this natural order to sort elements ascending.

The third parameter gives you the possibility to tell std::sort explicitly how this order shall be defined, imagine the following:

std::vector v({12, 7, 10});
std::sort(v.begin(), v.end(), [](int x, int y){return x > y;});

Looks unnatural, doesn't it? std::sort interprets the comparison as "less", but we implemented a "greater"! By doing so, the greater values then (as considered being "smaller") are sorted in front of smaller ones (considered being "greater"), so we have achieved sorting in descending order...

So the comparison parameter passed to std::sort is used to either sort differently to what the natural order would be or to define explicitly an order for data types where such order does not exist.

Side note: The order relation does not necessarily have to be a total order; however, equivalent elements then can be sorted in arbitrary order (you could, though, use std::stable_sort instead to at least preserve their relative order before sorting):

int a[12, 7, 10, 7];
std::vector<int*> v({&a[0], &a[1], &a[2], &a[3]});
std::sort(v.begin(), v.end(), [](int* x, int* y) { return *x < *y; });
// v[2] == &a[2]
// v[3] == &a[1]
// BUT:
// v[0] == &a[1] && v[1] == &a[3] || v[0] == &a[3] && v[1] == &a[1]
Aconcagua
  • 24,880
  • 4
  • 34
  • 59