[cmp.concept]

# 17 Language support library [[support]](./#support)

## 17.12 Comparisons [[cmp]](cmp#concept)

### 17.12.4 Concept three_way_comparable [cmp.concept]

template<class T, class Cat>concept [*compares-as*](#concept:compares-as "17.12.4 Concept three_­way_­comparable [cmp.concept]") = // *exposition only*[same_as](concept.same#concept:same_as "18.4.2 Concept same_­as [concept.same]")<common_comparison_category_t<T, Cat>, Cat>;

template<class T, class U>concept [*partially-ordered-with*](#concept:partially-ordered-with "17.12.4 Concept three_­way_­comparable [cmp.concept]") = // *exposition only*requires(const remove_reference_t<T>& t, const remove_reference_t<U>& u) {{ t < u } -> [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"); { t > u } -> [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"); { t <= u } -> [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"); { t >= u } -> [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"); { u < t } -> [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"); { u > t } -> [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"); { u <= t } -> [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"); { u >= t } -> [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"); };

[1](#1)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5340)

Let t and u be
lvalues of types const remove_reference_t<T> andconst remove_reference_t<U>, respectively[.](#1.sentence-1)

T and U model[*partially-ordered-with*](#concept:partially-ordered-with "17.12.4 Concept three_­way_­comparable [cmp.concept]")<T, U> only if

- [(1.1)](#1.1)

t < u, t <= u, t > u, t >= u, u < t, u <= t, u > t, and u >= t have the same domain,

- [(1.2)](#1.2)

bool(t < u) == bool(u > t) is true,

- [(1.3)](#1.3)

bool(u < t) == bool(t > u) is true,

- [(1.4)](#1.4)

bool(t <= u) == bool(u >= t) is true, and

- [(1.5)](#1.5)

bool(u <= t) == bool(t >= u) is true[.](#1.sentence-2)

template<class T, class Cat = partial_ordering>concept [three_way_comparable](#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]") =[*weakly-equality-comparable-with*](concept.equalitycomparable#concept:weakly-equality-comparable-with "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<T, T> &&[*partially-ordered-with*](#concept:partially-ordered-with "17.12.4 Concept three_­way_­comparable [cmp.concept]")<T, T> &&requires(const remove_reference_t<T>& a, const remove_reference_t<T>& b) {{ a <=> b } -> [*compares-as*](#concept:compares-as "17.12.4 Concept three_­way_­comparable [cmp.concept]")<Cat>; };

[2](#2)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5377)

Let a and b be lvalues
of type const remove_reference_t<T>[.](#2.sentence-1)

T and Cat model [three_way_comparable](#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<T, Cat> only if

- [(2.1)](#2.1)

(a <=> b == 0) == bool(a == b) is true,

- [(2.2)](#2.2)

(a <=> b != 0) == bool(a != b) is true,

- [(2.3)](#2.3)

((a <=> b) <=> 0) and (0 <=> (b <=> a)) are equal,

- [(2.4)](#2.4)

(a <=> b < 0) == bool(a < b) is true,

- [(2.5)](#2.5)

(a <=> b > 0) == bool(a > b) is true,

- [(2.6)](#2.6)

(a <=> b <= 0) == bool(a <= b) is true,

- [(2.7)](#2.7)

(a <=> b >= 0) == bool(a >= b) is true, and

- [(2.8)](#2.8)

if Cat is convertible to strong_ordering, T models [totally_ordered](concept.totallyordered#concept:totally_ordered "18.5.5 Concept totally_­ordered [concept.totallyordered]") ([[concept.totallyordered]](concept.totallyordered "18.5.5 Concept totally_­ordered"))[.](#2.sentence-2)

template<class T, class U, class Cat = partial_ordering>concept [three_way_comparable_with](#concept:three_way_comparable_with "17.12.4 Concept three_­way_­comparable [cmp.concept]") =[three_way_comparable](#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<T, Cat> &&[three_way_comparable](#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")<U, Cat> &&[*comparison-common-type-with*](concept.comparisoncommontype#concept:comparison-common-type-with "18.5.3 Comparison common types [concept.comparisoncommontype]")<T, U> &&[three_way_comparable](#concept:three_way_comparable "17.12.4 Concept three_­way_­comparable [cmp.concept]")< common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>, Cat> &&[*weakly-equality-comparable-with*](concept.equalitycomparable#concept:weakly-equality-comparable-with "18.5.4 Concept equality_­comparable [concept.equalitycomparable]")<T, U> &&[*partially-ordered-with*](#concept:partially-ordered-with "17.12.4 Concept three_­way_­comparable [cmp.concept]")<T, U> &&requires(const remove_reference_t<T>& t, const remove_reference_t<U>& u) {{ t <=> u } -> [*compares-as*](#concept:compares-as "17.12.4 Concept three_­way_­comparable [cmp.concept]")<Cat>; { u <=> t } -> [*compares-as*](#concept:compares-as "17.12.4 Concept three_­way_­comparable [cmp.concept]")<Cat>; };

[3](#3)

[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5418)

Let t and t2 be lvalues
denoting distinct equal objects
of types const remove_reference_t<T> andremove_cvref_t<T>, respectively, and
let u and u2 be lvalues denoting distinct equal objects
of types const remove_reference_t<U> andremove_cvref_t<U>, respectively[.](#3.sentence-1)

Let C becommon_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>[.](#3.sentence-2)

Let *CONVERT_TO_LVALUE*<C>(E) be defined
as in [[concepts.compare.general]](concepts.compare.general "18.5.1 General")[.](#3.sentence-3)

T, U, and Cat model [three_way_comparable_with](#concept:three_way_comparable_with "17.12.4 Concept three_­way_­comparable [cmp.concept]")<T, U, Cat> only if

- [(3.1)](#3.1)

t <=> u and u <=> t have the same domain,

- [(3.2)](#3.2)

((t <=> u) <=> 0) and (0 <=> (u <=> t)) are equal,

- [(3.3)](#3.3)

(t <=> u == 0) == bool(t == u) is true,

- [(3.4)](#3.4)

(t <=> u != 0) == bool(t != u) is true,

- [(3.5)](#3.5)

Cat(t <=> u) == Cat(*CONVERT_TO_LVALUE*<C>(t2) <=>*CONVERT_TO_LVALUE*<C>(u2)) is true,

- [(3.6)](#3.6)

(t <=> u < 0) == bool(t < u) is true,

- [(3.7)](#3.7)

(t <=> u > 0) == bool(t > u) is true,

- [(3.8)](#3.8)

(t <=> u <= 0) == bool(t <= u) is true,

- [(3.9)](#3.9)

(t <=> u >= 0) == bool(t >= u) is true, and

- [(3.10)](#3.10)

if Cat is convertible to strong_ordering, T and U model [totally_ordered_with](concept.totallyordered#concept:totally_ordered_with "18.5.5 Concept totally_­ordered [concept.totallyordered]")<T, U> ([[concept.totallyordered]](concept.totallyordered "18.5.5 Concept totally_­ordered"))[.](#3.sentence-4)
