#pragma once namespace types { template struct EqualityComparable { friend bool operator==(Self const & lhs, Self const & rhs) { return lhs.get() == rhs.get(); } friend bool operator!=(Self const & lhs, Self const & rhs) { return !(lhs == rhs); } #if __cplusplus >= 202002L friend std::partial_ordering operator<=>(Self const & lhs, Self const & rhs) { return lhs == rhs ? std::partial_ordering::equivalent : std::partial_ordering::unordered; } #endif }; template struct Comparable { friend bool operator==(Self const & lhs, Self const & rhs) { return lhs.get() == rhs.get(); } friend bool operator!=(Self const & lhs, Self const & rhs) { return !(lhs == rhs); } friend bool operator<(Self const & lhs, Self const & rhs) { return lhs.get() < rhs.get(); } friend bool operator>(Self const & lhs, Self const & rhs) { return rhs.get() < lhs.get(); } friend bool operator<=(Self const & lhs, Self const & rhs) { return !(rhs.get() < lhs.get()); } friend bool operator>=(Self const & lhs, Self const & rhs) { return !(lhs.get() < rhs.get()); } #if __cplusplus >= 202002L friend auto operator<=>(Self const & lhs, Self const & rhs) { return lhs.get() <=> rhs.get(); } #endif }; }