3

I have an std::vector of object for which I overloaded the < operator.

How can I use std::sort to sort it in descending order (without needing to write my own Comparator)?

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
user695652
  • 4,105
  • 7
  • 40
  • 58
  • 1
    `std::sort(begin(v), end(v), std::greater<>);` – SirGuy Jul 14 '16 at 18:57
  • 3
    `std::sort(v.rbegin(), v.rend());` – Piotr Skotnicki Jul 14 '16 at 18:58
  • Possible duplicate of [sorting a vector in descending order](http://stackoverflow.com/questions/9025084/sorting-a-vector-in-descending-order) – SirGuy Jul 14 '16 at 18:59
  • @ GuyGreer Could you explain why you don't need to specify the template argument and leave <> empty? – user695652 Jul 14 '16 at 19:04
  • 2
    As of C++14 there is a specialisation of the comparison functions and that is achieved by passing `void` as the template argument. At the same time, the standard made `void` the default template parameter if none is specified. The syntax `std::greater<>` instantiates the object with the default arguments – SirGuy Jul 14 '16 at 19:08
  • 1
    @GuyGreer but that object still needs to be instantiated, i.e., `std::greater<>()` – Piotr Skotnicki Jul 14 '16 at 20:02
  • @PiotrSkotnicki Yes, I forgot to do that and it's too late to edit it now – SirGuy Jul 14 '16 at 20:08

3 Answers3

7

You could simply transpose the arguments to std::less with the help of std::bind:

using namespace std::placeholders;
std::sort(v.begin(), v.end(), std::bind(std::less<T>{}, _2, _1));

But I think it'd be much cleaner to simply write the equivalent short lambda, even if it goes against the constraint of not writing your own Comparator:

std::sort(v.begin(), v.end(), [](T const& lhs, T const& rhs) { return rhs < lhs; });
Barry
  • 286,269
  • 29
  • 621
  • 977
  • Or even `std::greater` – SirGuy Jul 14 '16 at 18:58
  • @GuyGreer No, not `std::greater`. – Barry Jul 14 '16 at 18:59
  • 1
    while `std::greater` is not the same as `not2(std::less)`, I'm pretty sure they will give the same result while sorting... – SirGuy Jul 14 '16 at 19:00
  • @GuyGreer `std::greater` uses `operator>`. We don't have that. – Barry Jul 14 '16 at 19:02
  • 2
    @GuyGreer `std::greater` uses `operator>`, not `operator<`. An answer using that was posted and is deleted already. As for negating with `not_fn`, doesn't that give you `!(a < b)`, which is logically (when all relational operators are overloaded sensibly) `a >= b`, when you need `a > b`? –  Jul 14 '16 at 19:02
  • Ah, I just assumed that having `operator<` meant having `operator>`. My bad. – SirGuy Jul 14 '16 at 19:04
  • @hvd Yeah I guess you'd really need a `std::transpose2`... which I don't think exists. The part above the line is probably wrong. – Barry Jul 14 '16 at 19:05
  • 3
    @Barry Heh, good call, and I think that does exist, though not by that name: `std::bind(std::less(), std::placeholders::_2, std::placeholders::_1)`. The lambda goes against the OP's stated requirement of not creating a custom comparator. `std::bind` doesn't. Yet seeing this mess, I hope the OP has a change of heart and goes for the lambda anyway. :) –  Jul 14 '16 at 19:09
  • 2
    This seems like UB: If you sort `[1, 1]`, both comparisons will produce `true`. – Kerrek SB Jul 14 '16 at 19:09
  • @KerrekSB Yeah, I've struck it out. Totally wrong. I guess some people would say that having default comparisons would have solved this problem :) – Barry Jul 14 '16 at 19:12
  • Can you clarify the benefit of using the lambda vs reverse iterators as suggested in a comment by Piotr Skotnicki? – Mark B Jul 14 '16 at 19:13
  • @MarkB I think better to just ask Piotr to write an answer instead of always writing comments? I don't like using reverse iterators for anything more complicating than just walking through a container backwards. – Barry Jul 14 '16 at 19:14
3
std::sort(v.rbegin(), v.rend());
Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
0

You can sort array by using std::sort and then reverse it with std::reverse. This will sort in your desired way.

std::sort(v.begin(), v.end());
std::reverse(v.begin(), v.end());
Gynteniuxas
  • 7,035
  • 18
  • 38
  • 54
evan
  • 1,463
  • 1
  • 10
  • 13