Beginner's Guide

# Comparing Custom Types (Basics)Custom Comparisons (Basics)Comparisons

## Equality ComparisonsEqualityEquality

### Example: Comparable Integer IntervalExample: Integer IntervalExample

``````class irange { …
public: …
irange(int min, int max) … { … }

int min() const noexcept { … }
int max() const noexcept { … }

friend bool operator ==   (irange const& l, irange const& r) {
return l.min() == r.min() &&            l.max() == r.max();
}
friend bool operator !=   (irange const& l, irange const& r) {
return !(l == r);
}
};``````
``````#include "irange.hpp"
int main() {
irange s1 { 0,10};
irange s2 {10,20};
cout << (s1 == s2) << '\n';  // prints 0
}``````
You should implement 2-way comparison operator functions as "Hidden Friends"

###### Regarding the integer interval example:

Equality comparison has a straightforward meaning for intervals.

But it could mean several things that interval A is less than interval B:

• only the left bound of A could be smaller than the left bound of B,
• both bounds of A might be smaller than the left bound of B,
• or A might have a smaller width (max-min) than B.

⇒ ambiguous interface ⇒ don't implement smaller/larger comparisons for `irange`!

## Non-Equality ComparisonsNon-EqualityNon-Equality

### Example: Comparable DateExample: DateExample

``````enum class month { jan = 1, feb = 2, …, dec = 12 };
struct date {
int yyyy;   month mm;   int dd;

friend bool   operator < (date const& l, date const& r) {
if(l.yyyy < r.yyyy) return true;
if(l.yyyy > r.yyyy) return false;
if(l.mm < r.mm) return true;
if(l.mm > r.mm) return false;
if(l.dd < r.dd) return true;
return false;
}

// analogous...
friend bool operator <= ( … ) { … }
friend bool operator >  ( … ) { … }
friend bool operator >= ( … ) { … }
};``````
``````#include "month.hpp"
int main() {
date earlier {2017, month::dec, 24};
date later   {2018, month::may, 12};
// prints '1'
cout << (earlier < later) << '\n';
}``````

## 3-Way Comparisons  3-Way

``````(a <=> b) < 0     if a < b
(a <=> b) > 0     if a > b
(a <=> b) == 0    if a and b are equal``````

Operator `<=>` is predefined for fundamental types (`int`, `double`, …).

The return type of operator `<=>` is not an integer, but a comparison category object that is convertible to an integer.

### Defaulted DefinitionDefault

``````class C { …
auto operator <=> (C const&) = default;
};``````
• generates operators `<=>, <, <=, >, >=`
• default operators recursively compare data members in order of declaration
``````enum class month { jan = 1, feb = 2, …, dec = 12 };
struct date {
int yyyy;   month mm;   int dd;

auto operator <=> (date const&) = default;
};``````
``````int main() {
date earlier {2017, month::dec, 24};
date later   {2018, month::may, 12};
cout << (earlier <   later);  // 1
cout << (earlier >   later);  // 0
cout << (earlier <=> later);  // -1
}``````

### Manual DefinitionManual

``````enum class month { jan = 1, feb = 2, …, dec = 12 };
struct date {
int yyyy;   month mm;   int dd;

auto operator <=> (date const& o) {
// use built-in <=> for ints & enums
if(auto cmp = yyyy <=> o.yyyy;      cmp != 0) { return cmp; }
if(auto cmp = mm   <=> o.mm;        cmp != 0) { return cmp; }
return dd <=> o.dd;
}
};``````
``````int main() {
date earlier {2017, month::dec, 24};
date later   {2018, month::may, 12};
cout << (earlier <   later);  // 1
cout << (earlier >   later);  // 0
cout << (earlier <=> later);  // -1
}``````