Beginner's Guide
    First Steps
    Input & Output
    Basic Custom Types
    Diagnostics
    Standard Library
    Code Organization
    Powerful Custom Types
    Generic Programming
    Memory Management
    Software Design Basics

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

    Equality Comparisons Equality Equality

    Example: Comparable Integer Interval Example: Integer Interval Example

    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"

    Avoid overloading operators if the semantics is ambiguous!

    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 Comparisons Non-Equality Non-Equality

    Example: Comparable Date Example: Date Example

    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 Definition Default

    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 Definition Manual

    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
    }