6

How do I get operators >, >=, <=, and != from == and <?

standard header <utility> defines a namespace std::rel_ops that defines the above operators in terms of operators == and <, but I don't know how to use it (coax my code into using such definitions for:

std::sort(v.begin(), v.end(), std::greater<MyType>); 

where I have defined non-member operators:

bool operator < (const MyType & lhs, const MyType & rhs);
bool operator == (const MyType & lhs, const MyType & rhs);

If I #include <utility> and specify using namespace std::rel_ops; the compiler still complains that binary '>' : no operator found which takes a left-hand operand of type 'MyType'..

Mordachai
  • 9,412
  • 6
  • 60
  • 112
  • 1
    How does one say "compiler, please use std::rel_ops for MyType"? – Mordachai Feb 07 '13 at 16:55
  • [`boost::operators`](http://www.boost.org/doc/libs/1_53_0/libs/utility/operators.htm) ? – Robᵩ Feb 07 '13 at 16:59
  • I don't know. Maybe some `using` _declarations_ so it's picked up by _ADL_... It's easier to write those yourself, or if you are lazy you can leverage `Boost.Operators` – K-ballo Feb 07 '13 at 17:00
  • 1
    Well, that edit changes the question pretty substantially. – Robᵩ Feb 07 '13 at 17:14
  • Maybe the issue is I'm missing is ADL. Because my operators are non-member.. – Mordachai Feb 07 '13 at 17:15
  • I apologize if that edit throws anyone for a loop. Sometimes it's hard to know how to frame the question to get the response I need. Hopefully this revised question helps everyone understand what I'm really asking (and thanks to @K-ballo for supplying the std::rel_ops piece!) – Mordachai Feb 07 '13 at 17:16
  • That you wrote there is a `using` _directive_, not a `using` _declaration_. I was thinking something in the lines of `using std::rel_ops::operator!=` and the like. Which would augment the available operators for **every** type in your namespace, as well as other types that have your namespace as an associated namespace. Bottom line: don't do it – K-ballo Feb 07 '13 at 17:19
  • @Robᵩ thanks - that appears to be what I am looking for. – Mordachai Feb 07 '13 at 17:31

3 Answers3

8

I'd use the <boost/operators.hpp> header :

#include <boost/operators.hpp>

struct S : private boost::totally_ordered<S>
{
  bool operator<(const S&) const { return false; }
  bool operator==(const S&) const { return true; }
};

int main () {
  S s;
  s < s;
  s > s;
  s <= s;
  s >= s;
  s == s;
  s != s;
}

Or, if you prefer non-member operators:

#include <boost/operators.hpp>

struct S : private boost::totally_ordered<S>
{
};

bool operator<(const S&, const S&) { return false; }
bool operator==(const S&, const S&) { return true; }

int main () {
  S s;
  s < s;
  s > s;
  s <= s;
  s >= s;
  s == s;
  s != s;
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • 3
    Note: you could just use boost::totally_ordered instead of the multiple inheritance. Also, I tend to use private inheritance for this kind of thing. Finally, I know it is a trivial example, but operator==() should usually return true for stateless types. – Nevin Feb 07 '13 at 21:47
  • Note: I just checked that it works correctly with non-member operators (which I prefer when possible). – gx_ Nov 13 '13 at 15:26
1

Actually only < should suffice. Do it like so:

a == b <=> !(a<b) && !(b<a)

a > b <=> b < a

a <= b <=> !(b<a)

a != b <=> (a<b) || (b < a)

And so on for symmetric cases.

Ivaylo Strandjev
  • 69,226
  • 18
  • 123
  • 176
  • Ah - your answer is better. Was worried you could not use !, but you did :) – Michael Dorgan Feb 07 '13 at 16:57
  • I know how to do this myself - and they're simple one liners each. I just have a vague sense that there is a way to ask the standard library to supply those definitions in terms of the two I've already supplied. Seems silly to need to write the above for every T which defines `operator ==` and `operator <`, no? – Mordachai Feb 07 '13 at 16:58
  • 5
    `<` does not suffice. The `==` you implemented actually test for _equivalence_, not _equality_ – K-ballo Feb 07 '13 at 17:00
0

> equals !(&lt=)
>= equals !(&lt)
&lt= equals == or &lt
!= equals !(==)

Something like this?

Michael Dorgan
  • 12,453
  • 3
  • 31
  • 61