4

How I can specialize std::greater by using std::rel_ops? I have something like this

#include <utility>
#include <functional>

using namespace std::rel_ops;

struct MyStruct {
    int field;
    bool operator < (const MyStruct& rhs) const {
        return field < rhs.field;
    }
};

So I need to sort elements in descending order. How I can do it by using operator <, std::rel_ops and std::greater?

Null
  • 1,940
  • 9
  • 26
  • 32
AkhMa
  • 53
  • 5

3 Answers3

4

I'm assuming you tried to do something similar to

MyStruct ms[] = {{10}, {50}, {30}, {20}};
std::sort(std::begin(ms), std::end(ms), std::greater<MyStruct>{});

This fails to compile because no suitable operator> will be found. That's because std::greater relies upon ADL to find the operator overload, and ADL searches in associated namespaces. std::rel_ops is not an associated namespace for MyStruct. You can get everything to work by adding a using declaration to the same namespace as MyStruct so that the relevant operator> will be found.

using std::rel_ops::operator>;

Live demo

But this is ugly, and not a viable solution in general, so forget about std::rel_ops and use Boost.Operators as Barry suggests.

Community
  • 1
  • 1
Praetorian
  • 103,386
  • 18
  • 232
  • 318
  • Why do you think its ugly? it does exactly what it should do. – Surt Oct 16 '15 at 19:00
  • @Surt It's a matter of opinion of course, but if you wanted the other equality operators as well, then you'd need 4 using declarations. With Boost.Operators, you simply derive from `boost::totally_ordered` (after defining an `operator==` also for your type). – Praetorian Oct 16 '15 at 19:05
  • Well I like your solution as it doesn't need 3rd party includes. – Surt Oct 16 '15 at 19:09
1

You'd have to do it this way:

std::vector<MyStruct> v{...};

std::sort(v.begin(), v.end(), [](const MyStruct& lhs, const MyStruct& rhs){
    using namespace std::rel_ops;
    return lhs > rhs;
});

Although std::rel_ops is pretty lame. It's easier to use boost::less_than_comparable, in which you just add the operators directly into MyStruct:

struct MyStruct 
    : boost::less_than_comparable<MyStruct> // <== adds operator>,
                                            //          operator>=, 
                                            //      and operator<=
{
    MyStruct(int i) : field(i) { }
    int field;

    bool operator<(const MyStruct& rhs) const {
        return field < rhs.field;
    }
};

And then you can sort it the obvious way:

std::sort(v.begin(), v.end(), std::greater<MyStruct>());
Barry
  • 267,863
  • 28
  • 545
  • 906
0

std::rel_ops generate the other comparisons from == and < so you first need to define at least <

bool operator<(const MyStruct & lhs, const MyStruct & rhs) {
    return lhs.field < rhs.field;
}

Now rel_ops generate > so now you can use std::greater in std::sort

std::sort(begin(myVector), end(myVector), std::greater<MyStruct>());
Surt
  • 14,741
  • 3
  • 23
  • 36