namespace
<utility>

std::rel_ops

namespace rel_ops { template <class T> bool operator!= (const T& x, const T& y); template <class T> bool operator> (const T& x, const T& y); template <class T> bool operator<= (const T& x, const T& y); template <class T> bool operator>= (const T& x, const T& y);}
Relational Operators
This namespace declares template functions for four relational operators (!=,>, <=, and >=), deriving their behavior from operator== (for !=) and from operator< (for >,<=, and >=):

1
2
3
4
5
6
namespace rel_ops { template <class T> bool operator!= (const T& x, const T& y) { return !(x==y); } template <class T> bool operator> (const T& x, const T& y) { return y<x; } template <class T> bool operator<= (const T& x, const T& y) { return !(y<x); } template <class T> bool operator>= (const T& x, const T& y) { return !(x<y); } }

This avoids the necessity to declare all six relational operators for every complete type; By defining just two: operator== and operator<, and importing this namespace, all six operators will be defined for the type (they will not be selected by argument-dependent lookup when not importing it, though).

Notice that using this namespace introduces these overloads for all types not defining their own. Still, because non-template functions take precedence over template functions, any of these operators may be defined with a different behavior for a specific type.

Template parameters

T
For operator!=, the type shall be EqualityComparable.
A type is EqualityComparable when it supports operator== operations that follow the typical reflexive, symmetric and transitive properties of equalities.

For operator>, operator<=, and operator>=, the type shall be LessThanComparable.
A type is LessThanComparable when it supports operator< operations that define a valid strict weak ordering relation.

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// rel_ops example: #include <iostream> // std::cout, std::boolalpha #include <utility> // std::rel_ops #include <cmath> // std::sqrt class vector2d { public: double x,y; vector2d (double px,double py): x(px), y(py) {} double length() const {return std::sqrt(x*x+y*y);} bool operator==(const vector2d& rhs) const {return length()==rhs.length();} bool operator< (const vector2d& rhs) const {return length()< rhs.length();} }; int main () { using namespace std::rel_ops; vector2d a (10,10);// length=14.14 vector2d b (15,5);// length=15.81 std::cout << std::boolalpha; std::cout << "(a<b) is " << (a<b) << '\n'; std::cout << "(a>b) is " << (a>b) << '\n'; return 0; }

Output:
 (a<b) is true (a>b) is false 


Because we used rel_ops, all types for which operator< is defined (like vector2d) also have operator>.

Data races

The arguments are passed to the proper operator== or operator< overload, which can access them.
In any case, none of these functions can modify its arguments (const-qualified).

Exception safety

If the type of the elements supports the appropriate operation with no-throw guarantee, the function never throws exceptions (no-throw guarantee).

See also