840 lines
41 KiB
Markdown
840 lines
41 KiB
Markdown
[cmp]
|
||
|
||
# 17 Language support library [[support]](./#support)
|
||
|
||
## 17.12 Comparisons [cmp]
|
||
|
||
### [17.12.1](#compare.syn) Header <compare> synopsis [[compare.syn]](compare.syn)
|
||
|
||
[1](#compare.syn-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4783)
|
||
|
||
The header <compare> specifies types, objects, and functions
|
||
for use primarily in connection with
|
||
the [three-way comparison operator](expr.spaceship "7.6.8 Three-way comparison operator [expr.spaceship]")[.](#compare.syn-1.sentence-1)
|
||
|
||
[ð](#lib:is_eq)
|
||
|
||
// all freestandingnamespace std {// [[cmp.categories]](#categories "17.12.2 Comparison category types"), comparison category typesclass partial_ordering; class weak_ordering; class strong_ordering; // named comparison functionsconstexpr bool is_eq (partial_ordering cmp) noexcept { return cmp == 0; }constexpr bool is_neq (partial_ordering cmp) noexcept { return cmp != 0; }constexpr bool is_lt (partial_ordering cmp) noexcept { return cmp < 0; }constexpr bool is_lteq(partial_ordering cmp) noexcept { return cmp <= 0; }constexpr bool is_gt (partial_ordering cmp) noexcept { return cmp > 0; }constexpr bool is_gteq(partial_ordering cmp) noexcept { return cmp >= 0; }// [[cmp.common]](#common "17.12.3 Class template common_comparison_category"), common comparison category typetemplate<class... Ts>struct common_comparison_category {using type = *see below*; }; template<class... Ts>using common_comparison_category_t = typename common_comparison_category<Ts...>::type; // [[cmp.concept]](#concept "17.12.4 Concept three_way_comparable"), concept [three_way_comparable](#concept:three_way_comparable "17.12.4 Concept three_way_comparable [cmp.concept]")template<class T, class Cat = partial_ordering>concept three_way_comparable = *see below*; template<class T, class U, class Cat = partial_ordering>concept three_way_comparable_with = *see below*; // [[cmp.result]](#result "17.12.5 Result of three-way comparison"), result of three-way comparisontemplate<class T, class U = T> struct compare_three_way_result; template<class T, class U = T>using compare_three_way_result_t = typename compare_three_way_result<T, U>::type; // [[comparisons.three.way]](comparisons.three.way "22.10.8.8 Class compare_three_way"), class compare_three_waystruct compare_three_way; // [[cmp.alg]](#alg "17.12.6 Comparison algorithms"), comparison algorithmsinline namespace *unspecified* {inline constexpr *unspecified* strong_order = *unspecified*; inline constexpr *unspecified* weak_order = *unspecified*; inline constexpr *unspecified* partial_order = *unspecified*; inline constexpr *unspecified* compare_strong_order_fallback = *unspecified*; inline constexpr *unspecified* compare_weak_order_fallback = *unspecified*; inline constexpr *unspecified* compare_partial_order_fallback = *unspecified*; }// [[compare.type]](#compare.type "17.12.7 Type Ordering"), type orderingtemplate<class T, class U>struct type_order; template<class T, class U>constexpr strong_ordering type_order_v = type_order<T, U>::value;}
|
||
|
||
### [17.12.2](#categories) Comparison category types [[cmp.categories]](cmp.categories)
|
||
|
||
#### [17.12.2.1](#categories.pre) Preamble [[cmp.categories.pre]](cmp.categories.pre)
|
||
|
||
[1](#categories.pre-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4859)
|
||
|
||
The typespartial_ordering,weak_ordering, andstrong_ordering are collectively termed the [*comparison category types*](#def:comparison_category_types "17.12.2.1 Preamble [cmp.categories.pre]")[.](#categories.pre-1.sentence-1)
|
||
|
||
Each is specified in terms of an exposition-only data member named value whose value typically corresponds to that of an enumerator
|
||
from one of the following exposition-only enumerations:enum class *ord* { *equal* = 0, *equivalent* = *equal*, *less* = -1, *greater* = 1 }; // *exposition only*enum class *ncmp* { *unordered* = -127 }; // *exposition only*
|
||
|
||
[2](#categories.pre-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4873)
|
||
|
||
[*Note [1](#categories.pre-note-1)*:
|
||
|
||
The type strong_ordering corresponds to the term
|
||
total ordering in mathematics[.](#categories.pre-2.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[3](#categories.pre-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4880)
|
||
|
||
The relational and equality operators for the comparison category types
|
||
are specified with an anonymous parameter of unspecified type[.](#categories.pre-3.sentence-1)
|
||
|
||
This type shall be selected by the implementation such that
|
||
these parameters can accept literal 0 as a corresponding argument[.](#categories.pre-3.sentence-2)
|
||
|
||
[*Example [1](#categories.pre-example-1)*:
|
||
|
||
nullptr_t meets this requirement[.](#categories.pre-3.sentence-3)
|
||
|
||
â *end example*]
|
||
|
||
In this context, the behavior of a program that supplies
|
||
an argument other than a literal 0 is undefined[.](#categories.pre-3.sentence-4)
|
||
|
||
[4](#categories.pre-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4892)
|
||
|
||
For the purposes of [[cmp.categories]](#categories "17.12.2 Comparison category types"),[*substitutability*](#def:substitutability "17.12.2.1 Preamble [cmp.categories.pre]") is the property that f(a) == f(b) is true whenever a == b is true,
|
||
where f denotes a function that reads only comparison-salient state
|
||
that is accessible via the argument's public const members[.](#categories.pre-4.sentence-1)
|
||
|
||
#### [17.12.2.2](#partialord) Class partial_ordering [[cmp.partialord]](cmp.partialord)
|
||
|
||
[1](#partialord-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4901)
|
||
|
||
The partial_ordering type is typically used
|
||
as the result type of a three-way comparison operator ([[expr.spaceship]](expr.spaceship "7.6.8 Three-way comparison operator"))
|
||
for a type that admits
|
||
all of the six two-way comparison operators ([[expr.rel]](expr.rel "7.6.9 Relational operators"), [[expr.eq]](expr.eq "7.6.10 Equality operators")),
|
||
for which equality need not imply substitutability,
|
||
and that permits two values to be incomparable[.](#partialord-1.sentence-1)[190](#footnote-190 "That is, a < b, a == b, and a > b might all be false.")
|
||
|
||
[ð](#lib:partial_ordering)
|
||
|
||
namespace std {class partial_ordering {int *value*; // *exposition only*bool *is-ordered*; // *exposition only*// exposition-only constructorsconstexpr explicit partial_ordering(*ord* v) noexcept : *value*(int(v)), *is-ordered*(true) {} // *exposition only*constexpr explicit partial_ordering(*ncmp* v) noexcept : *value*(int(v)), *is-ordered*(false) {} // *exposition only*public:// valid valuesstatic const partial_ordering less; static const partial_ordering equivalent; static const partial_ordering greater; static const partial_ordering unordered; // comparisonsfriend constexpr bool operator==(partial_ordering v, *unspecified*) noexcept; friend constexpr bool operator==(partial_ordering v, partial_ordering w) noexcept = default; friend constexpr bool operator< (partial_ordering v, *unspecified*) noexcept; friend constexpr bool operator> (partial_ordering v, *unspecified*) noexcept; friend constexpr bool operator<=(partial_ordering v, *unspecified*) noexcept; friend constexpr bool operator>=(partial_ordering v, *unspecified*) noexcept; friend constexpr bool operator< (*unspecified*, partial_ordering v) noexcept; friend constexpr bool operator> (*unspecified*, partial_ordering v) noexcept; friend constexpr bool operator<=(*unspecified*, partial_ordering v) noexcept; friend constexpr bool operator>=(*unspecified*, partial_ordering v) noexcept; friend constexpr partial_ordering operator<=>(partial_ordering v, *unspecified*) noexcept; friend constexpr partial_ordering operator<=>(*unspecified*, partial_ordering v) noexcept; }; // valid values' definitionsinline constexpr partial_ordering partial_ordering::less(*ord*::*less*); inline constexpr partial_ordering partial_ordering::equivalent(*ord*::*equivalent*); inline constexpr partial_ordering partial_ordering::greater(*ord*::*greater*); inline constexpr partial_ordering partial_ordering::unordered(*ncmp*::*unordered*);}
|
||
|
||
[ð](#lib:operator==,partial_ordering)
|
||
|
||
`constexpr bool operator==(partial_ordering v, unspecified) noexcept;
|
||
constexpr bool operator< (partial_ordering v, unspecified) noexcept;
|
||
constexpr bool operator> (partial_ordering v, unspecified) noexcept;
|
||
constexpr bool operator<=(partial_ordering v, unspecified) noexcept;
|
||
constexpr bool operator>=(partial_ordering v, unspecified) noexcept;
|
||
`
|
||
|
||
[2](#partialord-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4973)
|
||
|
||
*Returns*: For operator@, v.*is-ordered* && v.*value* @ 0[.](#partialord-2.sentence-1)
|
||
|
||
[ð](#lib:operator%3c,partial_ordering_)
|
||
|
||
`constexpr bool operator< (unspecified, partial_ordering v) noexcept;
|
||
constexpr bool operator> (unspecified, partial_ordering v) noexcept;
|
||
constexpr bool operator<=(unspecified, partial_ordering v) noexcept;
|
||
constexpr bool operator>=(unspecified, partial_ordering v) noexcept;
|
||
`
|
||
|
||
[3](#partialord-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L4990)
|
||
|
||
*Returns*: For operator@, v.*is-ordered* && 0 @ v.*value*[.](#partialord-3.sentence-1)
|
||
|
||
[ð](#lib:operator%3c=%3e,partial_ordering)
|
||
|
||
`constexpr partial_ordering operator<=>(partial_ordering v, unspecified) noexcept;
|
||
`
|
||
|
||
[4](#partialord-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5001)
|
||
|
||
*Returns*: v[.](#partialord-4.sentence-1)
|
||
|
||
[ð](#lib:operator%3c=%3e,partial_ordering_)
|
||
|
||
`constexpr partial_ordering operator<=>(unspecified, partial_ordering v) noexcept;
|
||
`
|
||
|
||
[5](#partialord-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5012)
|
||
|
||
*Returns*: v < 0 ? partial_ordering::greater : v > 0 ? partial_ordering::less : v[.](#partialord-5.sentence-1)
|
||
|
||
[190)](#footnote-190)[190)](#footnoteref-190)
|
||
|
||
That is, a < b, a == b, and a > b might all be false[.](#footnote-190.sentence-1)
|
||
|
||
#### [17.12.2.3](#weakord) Class weak_ordering [[cmp.weakord]](cmp.weakord)
|
||
|
||
[1](#weakord-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5019)
|
||
|
||
The weak_ordering type is typically used
|
||
as the result type of a three-way comparison operator ([[expr.spaceship]](expr.spaceship "7.6.8 Three-way comparison operator"))
|
||
for a type that admits
|
||
all of the six two-way comparison operators ([[expr.rel]](expr.rel "7.6.9 Relational operators"), [[expr.eq]](expr.eq "7.6.10 Equality operators"))
|
||
and for which equality need not imply substitutability[.](#weakord-1.sentence-1)
|
||
|
||
[ð](#lib:weak_ordering)
|
||
|
||
namespace std {class weak_ordering {int *value*; // *exposition only*// exposition-only constructorsconstexpr explicit weak_ordering(*ord* v) noexcept : *value*(int(v)) {} // *exposition only*public:// valid valuesstatic const weak_ordering less; static const weak_ordering equivalent; static const weak_ordering greater; // conversionsconstexpr operator partial_ordering() const noexcept; // comparisonsfriend constexpr bool operator==(weak_ordering v, *unspecified*) noexcept; friend constexpr bool operator==(weak_ordering v, weak_ordering w) noexcept = default; friend constexpr bool operator< (weak_ordering v, *unspecified*) noexcept; friend constexpr bool operator> (weak_ordering v, *unspecified*) noexcept; friend constexpr bool operator<=(weak_ordering v, *unspecified*) noexcept; friend constexpr bool operator>=(weak_ordering v, *unspecified*) noexcept; friend constexpr bool operator< (*unspecified*, weak_ordering v) noexcept; friend constexpr bool operator> (*unspecified*, weak_ordering v) noexcept; friend constexpr bool operator<=(*unspecified*, weak_ordering v) noexcept; friend constexpr bool operator>=(*unspecified*, weak_ordering v) noexcept; friend constexpr weak_ordering operator<=>(weak_ordering v, *unspecified*) noexcept; friend constexpr weak_ordering operator<=>(*unspecified*, weak_ordering v) noexcept; }; // valid values' definitionsinline constexpr weak_ordering weak_ordering::less(*ord*::*less*); inline constexpr weak_ordering weak_ordering::equivalent(*ord*::*equivalent*); inline constexpr weak_ordering weak_ordering::greater(*ord*::*greater*);}
|
||
|
||
[ð](#lib:operator_partial_ordering,weak_ordering)
|
||
|
||
`constexpr operator partial_ordering() const noexcept;
|
||
`
|
||
|
||
[2](#weakord-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5075)
|
||
|
||
*Returns*: *value* == 0 ? partial_ordering::equivalent :*value* < 0 ? partial_ordering::less : partial_ordering::greater
|
||
|
||
[ð](#lib:operator==,weak_ordering)
|
||
|
||
`constexpr bool operator==(weak_ordering v, unspecified) noexcept;
|
||
constexpr bool operator< (weak_ordering v, unspecified) noexcept;
|
||
constexpr bool operator> (weak_ordering v, unspecified) noexcept;
|
||
constexpr bool operator<=(weak_ordering v, unspecified) noexcept;
|
||
constexpr bool operator>=(weak_ordering v, unspecified) noexcept;
|
||
`
|
||
|
||
[3](#weakord-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5098)
|
||
|
||
*Returns*: v.*value* @ 0 for operator@[.](#weakord-3.sentence-1)
|
||
|
||
[ð](#lib:operator%3c,weak_ordering_)
|
||
|
||
`constexpr bool operator< (unspecified, weak_ordering v) noexcept;
|
||
constexpr bool operator> (unspecified, weak_ordering v) noexcept;
|
||
constexpr bool operator<=(unspecified, weak_ordering v) noexcept;
|
||
constexpr bool operator>=(unspecified, weak_ordering v) noexcept;
|
||
`
|
||
|
||
[4](#weakord-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5115)
|
||
|
||
*Returns*: 0 @ v.*value* for operator@[.](#weakord-4.sentence-1)
|
||
|
||
[ð](#lib:operator%3c=%3e,weak_ordering)
|
||
|
||
`constexpr weak_ordering operator<=>(weak_ordering v, unspecified) noexcept;
|
||
`
|
||
|
||
[5](#weakord-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5126)
|
||
|
||
*Returns*: v[.](#weakord-5.sentence-1)
|
||
|
||
[ð](#lib:operator%3c=%3e,weak_ordering_)
|
||
|
||
`constexpr weak_ordering operator<=>(unspecified, weak_ordering v) noexcept;
|
||
`
|
||
|
||
[6](#weakord-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5137)
|
||
|
||
*Returns*: v < 0 ? weak_ordering::greater : v > 0 ? weak_ordering::less : v[.](#weakord-6.sentence-1)
|
||
|
||
#### [17.12.2.4](#strongord) Class strong_ordering [[cmp.strongord]](cmp.strongord)
|
||
|
||
[1](#strongord-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5144)
|
||
|
||
The strong_ordering type is typically used
|
||
as the result type of a three-way comparison operator ([[expr.spaceship]](expr.spaceship "7.6.8 Three-way comparison operator"))
|
||
for a type that admits
|
||
all of the six two-way comparison operators ([[expr.rel]](expr.rel "7.6.9 Relational operators"), [[expr.eq]](expr.eq "7.6.10 Equality operators"))
|
||
and for which equality does imply substitutability[.](#strongord-1.sentence-1)
|
||
|
||
[ð](#lib:strong_ordering)
|
||
|
||
namespace std {class strong_ordering {int *value*; // *exposition only*// exposition-only constructorsconstexpr explicit strong_ordering(*ord* v) noexcept : *value*(int(v)) {} // *exposition only*public:// valid valuesstatic const strong_ordering less; static const strong_ordering equal; static const strong_ordering equivalent; static const strong_ordering greater; // conversionsconstexpr operator partial_ordering() const noexcept; constexpr operator weak_ordering() const noexcept; // comparisonsfriend constexpr bool operator==(strong_ordering v, *unspecified*) noexcept; friend constexpr bool operator==(strong_ordering v, strong_ordering w) noexcept = default; friend constexpr bool operator< (strong_ordering v, *unspecified*) noexcept; friend constexpr bool operator> (strong_ordering v, *unspecified*) noexcept; friend constexpr bool operator<=(strong_ordering v, *unspecified*) noexcept; friend constexpr bool operator>=(strong_ordering v, *unspecified*) noexcept; friend constexpr bool operator< (*unspecified*, strong_ordering v) noexcept; friend constexpr bool operator> (*unspecified*, strong_ordering v) noexcept; friend constexpr bool operator<=(*unspecified*, strong_ordering v) noexcept; friend constexpr bool operator>=(*unspecified*, strong_ordering v) noexcept; friend constexpr strong_ordering operator<=>(strong_ordering v, *unspecified*) noexcept; friend constexpr strong_ordering operator<=>(*unspecified*, strong_ordering v) noexcept; }; // valid values' definitionsinline constexpr strong_ordering strong_ordering::less(*ord*::*less*); inline constexpr strong_ordering strong_ordering::equal(*ord*::*equal*); inline constexpr strong_ordering strong_ordering::equivalent(*ord*::*equivalent*); inline constexpr strong_ordering strong_ordering::greater(*ord*::*greater*);}
|
||
|
||
[ð](#lib:operator_partial_ordering,strong_ordering)
|
||
|
||
`constexpr operator partial_ordering() const noexcept;
|
||
`
|
||
|
||
[2](#strongord-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5204)
|
||
|
||
*Returns*: *value* == 0 ? partial_ordering::equivalent :*value* < 0 ? partial_ordering::less : partial_ordering::greater
|
||
|
||
[ð](#lib:operator_weak_ordering,strong_ordering)
|
||
|
||
`constexpr operator weak_ordering() const noexcept;
|
||
`
|
||
|
||
[3](#strongord-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5219)
|
||
|
||
*Returns*: *value* == 0 ? weak_ordering::equivalent :*value* < 0 ? weak_ordering::less : weak_ordering::greater
|
||
|
||
[ð](#lib:operator==,strong_ordering)
|
||
|
||
`constexpr bool operator==(strong_ordering v, unspecified) noexcept;
|
||
constexpr bool operator< (strong_ordering v, unspecified) noexcept;
|
||
constexpr bool operator> (strong_ordering v, unspecified) noexcept;
|
||
constexpr bool operator<=(strong_ordering v, unspecified) noexcept;
|
||
constexpr bool operator>=(strong_ordering v, unspecified) noexcept;
|
||
`
|
||
|
||
[4](#strongord-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5242)
|
||
|
||
*Returns*: v.*value* @ 0 for operator@[.](#strongord-4.sentence-1)
|
||
|
||
[ð](#lib:operator%3c,strong_ordering_)
|
||
|
||
`constexpr bool operator< (unspecified, strong_ordering v) noexcept;
|
||
constexpr bool operator> (unspecified, strong_ordering v) noexcept;
|
||
constexpr bool operator<=(unspecified, strong_ordering v) noexcept;
|
||
constexpr bool operator>=(unspecified, strong_ordering v) noexcept;
|
||
`
|
||
|
||
[5](#strongord-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5259)
|
||
|
||
*Returns*: 0 @ v.*value* for operator@[.](#strongord-5.sentence-1)
|
||
|
||
[ð](#lib:operator%3c=%3e,strong_ordering)
|
||
|
||
`constexpr strong_ordering operator<=>(strong_ordering v, unspecified) noexcept;
|
||
`
|
||
|
||
[6](#strongord-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5270)
|
||
|
||
*Returns*: v[.](#strongord-6.sentence-1)
|
||
|
||
[ð](#lib:operator%3c=%3e,strong_ordering_)
|
||
|
||
`constexpr strong_ordering operator<=>(unspecified, strong_ordering v) noexcept;
|
||
`
|
||
|
||
[7](#strongord-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5281)
|
||
|
||
*Returns*: v < 0 ? strong_ordering::greater : v > 0 ? strong_ordering::less : v[.](#strongord-7.sentence-1)
|
||
|
||
### [17.12.3](#common) Class template common_comparison_category [[cmp.common]](cmp.common)
|
||
|
||
[1](#common-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5288)
|
||
|
||
The type common_comparison_category provides an alias for
|
||
the strongest comparison category
|
||
to which all of the template arguments can be converted[.](#common-1.sentence-1)
|
||
|
||
[*Note [1](#common-note-1)*:
|
||
|
||
A comparison category type is stronger than another if
|
||
they are distinct types and an instance of the former
|
||
can be converted to an instance of the latter[.](#common-1.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:common_comparison_category)
|
||
|
||
`template<class... Ts>
|
||
struct common_comparison_category {
|
||
using type = see below;
|
||
};
|
||
`
|
||
|
||
[2](#common-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5307)
|
||
|
||
*Remarks*: The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") type denotes
|
||
the common comparison type ([[class.spaceship]](class.spaceship "11.10.3 Three-way comparison")) of Ts...,
|
||
the expanded parameter pack, orvoid if any element of Ts is not a comparison category type[.](#common-2.sentence-1)
|
||
|
||
[*Note [2](#common-note-2)*:
|
||
|
||
This is std::strong_ordering if the expansion is empty[.](#common-2.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
### [17.12.4](#concept) Concept three_way_comparable [[cmp.concept]](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](#concept-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[.](#concept-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)](#concept-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)](#concept-1.2)
|
||
|
||
bool(t < u) == bool(u > t) is true,
|
||
|
||
- [(1.3)](#concept-1.3)
|
||
|
||
bool(u < t) == bool(t > u) is true,
|
||
|
||
- [(1.4)](#concept-1.4)
|
||
|
||
bool(t <= u) == bool(u >= t) is true, and
|
||
|
||
- [(1.5)](#concept-1.5)
|
||
|
||
bool(u <= t) == bool(t >= u) is true[.](#concept-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](#concept-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>[.](#concept-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)](#concept-2.1)
|
||
|
||
(a <=> b == 0) == bool(a == b) is true,
|
||
|
||
- [(2.2)](#concept-2.2)
|
||
|
||
(a <=> b != 0) == bool(a != b) is true,
|
||
|
||
- [(2.3)](#concept-2.3)
|
||
|
||
((a <=> b) <=> 0) and (0 <=> (b <=> a)) are equal,
|
||
|
||
- [(2.4)](#concept-2.4)
|
||
|
||
(a <=> b < 0) == bool(a < b) is true,
|
||
|
||
- [(2.5)](#concept-2.5)
|
||
|
||
(a <=> b > 0) == bool(a > b) is true,
|
||
|
||
- [(2.6)](#concept-2.6)
|
||
|
||
(a <=> b <= 0) == bool(a <= b) is true,
|
||
|
||
- [(2.7)](#concept-2.7)
|
||
|
||
(a <=> b >= 0) == bool(a >= b) is true, and
|
||
|
||
- [(2.8)](#concept-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"))[.](#concept-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](#concept-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[.](#concept-3.sentence-1)
|
||
|
||
Let C becommon_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>[.](#concept-3.sentence-2)
|
||
|
||
Let *CONVERT_TO_LVALUE*<C>(E) be defined
|
||
as in [[concepts.compare.general]](concepts.compare.general "18.5.1 General")[.](#concept-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)](#concept-3.1)
|
||
|
||
t <=> u and u <=> t have the same domain,
|
||
|
||
- [(3.2)](#concept-3.2)
|
||
|
||
((t <=> u) <=> 0) and (0 <=> (u <=> t)) are equal,
|
||
|
||
- [(3.3)](#concept-3.3)
|
||
|
||
(t <=> u == 0) == bool(t == u) is true,
|
||
|
||
- [(3.4)](#concept-3.4)
|
||
|
||
(t <=> u != 0) == bool(t != u) is true,
|
||
|
||
- [(3.5)](#concept-3.5)
|
||
|
||
Cat(t <=> u) == Cat(*CONVERT_TO_LVALUE*<C>(t2) <=>*CONVERT_TO_LVALUE*<C>(u2)) is true,
|
||
|
||
- [(3.6)](#concept-3.6)
|
||
|
||
(t <=> u < 0) == bool(t < u) is true,
|
||
|
||
- [(3.7)](#concept-3.7)
|
||
|
||
(t <=> u > 0) == bool(t > u) is true,
|
||
|
||
- [(3.8)](#concept-3.8)
|
||
|
||
(t <=> u <= 0) == bool(t <= u) is true,
|
||
|
||
- [(3.9)](#concept-3.9)
|
||
|
||
(t <=> u >= 0) == bool(t >= u) is true, and
|
||
|
||
- [(3.10)](#concept-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"))[.](#concept-3.sentence-4)
|
||
|
||
### [17.12.5](#result) Result of three-way comparison [[cmp.result]](cmp.result)
|
||
|
||
[1](#result-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5460)
|
||
|
||
The behavior of a program
|
||
that adds specializations for the compare_three_way_result template
|
||
defined in this subclause is undefined[.](#result-1.sentence-1)
|
||
|
||
[2](#result-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5465)
|
||
|
||
For the compare_three_way_result type trait
|
||
applied to the types T and U,
|
||
let t and u denote lvalues of typesconst remove_reference_t<T> and const remove_reference_t<U>,
|
||
respectively[.](#result-2.sentence-1)
|
||
|
||
If the expression t <=> u is well-formed
|
||
when treated as an unevaluated operand ([[expr.context]](expr.context "7.2.3 Context dependence")),
|
||
the member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") type denotes the type decltype(t <=> u)[.](#result-2.sentence-2)
|
||
|
||
Otherwise, there is no member type[.](#result-2.sentence-3)
|
||
|
||
### [17.12.6](#alg) Comparison algorithms [[cmp.alg]](cmp.alg)
|
||
|
||
[1](#alg-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5480)
|
||
|
||
The name strong_order denotes
|
||
a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#alg-1.sentence-1)
|
||
|
||
Given subexpressions E and F,
|
||
the expression strong_order(E, F) is expression-equivalent ([[defns.expression.equivalent]](defns.expression.equivalent "3.22 expression-equivalent")) to the following:
|
||
|
||
- [(1.1)](#alg-1.1)
|
||
|
||
If the decayed types of E and F differ, strong_order(E, F) is ill-formed[.](#alg-1.1.sentence-1)
|
||
|
||
- [(1.2)](#alg-1.2)
|
||
|
||
Otherwise, strong_ordering(strong_order(E, F)) if it is a well-formed expression
|
||
where the meaning of strong_order is established as-if by performing
|
||
argument-dependent lookup only ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup"))[.](#alg-1.2.sentence-1)
|
||
|
||
- [(1.3)](#alg-1.3)
|
||
|
||
Otherwise, if the decayed type T of E is
|
||
a floating-point type,
|
||
yields a value of type strong_ordering that is consistent with the ordering
|
||
observed by T's comparison operators, and
|
||
if numeric_limits<T>::is_iec559 is true,
|
||
is additionally consistent with the totalOrder operation
|
||
as specified in ISO/IEC 60559[.](#alg-1.3.sentence-1)
|
||
|
||
- [(1.4)](#alg-1.4)
|
||
|
||
Otherwise, strong_ordering(compare_three_way()(E, F)) if it is a well-formed expression[.](#alg-1.4.sentence-1)
|
||
|
||
- [(1.5)](#alg-1.5)
|
||
|
||
Otherwise, strong_order(E, F) is ill-formed[.](#alg-1.5.sentence-1)
|
||
|
||
[*Note [1](#alg-note-1)*:
|
||
|
||
Ill-formed cases above result in substitution failure
|
||
when strong_order(E, F) appears in the immediate context
|
||
of a template instantiation[.](#alg-1.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[2](#alg-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5518)
|
||
|
||
The name weak_order denotes
|
||
a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#alg-2.sentence-1)
|
||
|
||
Given subexpressions E and F,
|
||
the expression weak_order(E, F) is expression-equivalent ([[defns.expression.equivalent]](defns.expression.equivalent "3.22 expression-equivalent")) to the following:
|
||
|
||
- [(2.1)](#alg-2.1)
|
||
|
||
If the decayed types of E and F differ, weak_order(E, F) is ill-formed[.](#alg-2.1.sentence-1)
|
||
|
||
- [(2.2)](#alg-2.2)
|
||
|
||
Otherwise, weak_ordering(weak_order(E, F)) if it is a well-formed expression
|
||
where the meaning of weak_order is established as-if by performing
|
||
argument-dependent lookup only ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup"))[.](#alg-2.2.sentence-1)
|
||
|
||
- [(2.3)](#alg-2.3)
|
||
|
||
Otherwise, if the decayed type T of E is a floating-point type,
|
||
yields a value of type weak_ordering that is consistent with the ordering
|
||
observed by T's comparison operators and strong_order, and
|
||
if numeric_limits<T>::is_iec559 is true,
|
||
is additionally consistent with the following equivalence classes,
|
||
ordered from lesser to greater:
|
||
* [(2.3.1)](#alg-2.3.1)
|
||
|
||
together, all negative NaN values;
|
||
|
||
* [(2.3.2)](#alg-2.3.2)
|
||
|
||
negative infinity;
|
||
|
||
* [(2.3.3)](#alg-2.3.3)
|
||
|
||
each normal negative value;
|
||
|
||
* [(2.3.4)](#alg-2.3.4)
|
||
|
||
each subnormal negative value;
|
||
|
||
* [(2.3.5)](#alg-2.3.5)
|
||
|
||
together, both zero values;
|
||
|
||
* [(2.3.6)](#alg-2.3.6)
|
||
|
||
each subnormal positive value;
|
||
|
||
* [(2.3.7)](#alg-2.3.7)
|
||
|
||
each normal positive value;
|
||
|
||
* [(2.3.8)](#alg-2.3.8)
|
||
|
||
positive infinity;
|
||
|
||
* [(2.3.9)](#alg-2.3.9)
|
||
|
||
together, all positive NaN values[.](#alg-2.3.sentence-1)
|
||
|
||
- [(2.4)](#alg-2.4)
|
||
|
||
Otherwise, weak_ordering(compare_three_way()(E, F)) if it is a well-formed expression[.](#alg-2.4.sentence-1)
|
||
|
||
- [(2.5)](#alg-2.5)
|
||
|
||
Otherwise, weak_ordering(strong_order(E, F)) if it is a well-formed expression[.](#alg-2.5.sentence-1)
|
||
|
||
- [(2.6)](#alg-2.6)
|
||
|
||
Otherwise, weak_order(E, F) is ill-formed[.](#alg-2.6.sentence-1)
|
||
|
||
[*Note [2](#alg-note-2)*:
|
||
|
||
Ill-formed cases above result in substitution failure
|
||
when weak_order(E, F) appears in the immediate context
|
||
of a template instantiation[.](#alg-2.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[3](#alg-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5570)
|
||
|
||
The name partial_order denotes
|
||
a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#alg-3.sentence-1)
|
||
|
||
Given subexpressions E and F,
|
||
the expression partial_order(E, F) is expression-equivalent ([[defns.expression.equivalent]](defns.expression.equivalent "3.22 expression-equivalent")) to the following:
|
||
|
||
- [(3.1)](#alg-3.1)
|
||
|
||
If the decayed types of E and F differ, partial_order(E, F) is ill-formed[.](#alg-3.1.sentence-1)
|
||
|
||
- [(3.2)](#alg-3.2)
|
||
|
||
Otherwise, partial_ordering(partial_order(E, F)) if it is a well-formed expression
|
||
where the meaning of partial_order is established as-if by performing
|
||
argument-dependent lookup only ([[basic.lookup.argdep]](basic.lookup.argdep "6.5.4 Argument-dependent name lookup"))[.](#alg-3.2.sentence-1)
|
||
|
||
- [(3.3)](#alg-3.3)
|
||
|
||
Otherwise, partial_ordering(compare_three_way()(E, F)) if it is a well-formed expression[.](#alg-3.3.sentence-1)
|
||
|
||
- [(3.4)](#alg-3.4)
|
||
|
||
Otherwise, partial_ordering(weak_order(E, F)) if it is a well-formed expression[.](#alg-3.4.sentence-1)
|
||
|
||
- [(3.5)](#alg-3.5)
|
||
|
||
Otherwise, partial_order(E, F) is ill-formed[.](#alg-3.5.sentence-1)
|
||
|
||
[*Note [3](#alg-note-3)*:
|
||
|
||
Ill-formed cases above result in substitution failure
|
||
when partial_order(E, F) appears in the immediate context
|
||
of a template instantiation[.](#alg-3.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[4](#alg-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5602)
|
||
|
||
The name compare_strong_order_fallback denotes a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#alg-4.sentence-1)
|
||
|
||
Given subexpressions E and F,
|
||
the expression compare_strong_order_fallback(E, F) is expression-equivalent ([[defns.expression.equivalent]](defns.expression.equivalent "3.22 expression-equivalent")) to:
|
||
|
||
- [(4.1)](#alg-4.1)
|
||
|
||
If the decayed types of E and F differ, compare_strong_order_fallback(E, F) is ill-formed[.](#alg-4.1.sentence-1)
|
||
|
||
- [(4.2)](#alg-4.2)
|
||
|
||
Otherwise, strong_order(E, F) if it is a well-formed expression[.](#alg-4.2.sentence-1)
|
||
|
||
- [(4.3)](#alg-4.3)
|
||
|
||
Otherwise, if the expressions E == F and E < F are both well-formed and
|
||
each of decltype(E == F) and decltype(E < F) models [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"),E == F ? strong_ordering::equal : E < F ? strong_ordering::less : strong_ordering::greater except that E and F are evaluated only once[.](#alg-4.3.sentence-1)
|
||
|
||
- [(4.4)](#alg-4.4)
|
||
|
||
Otherwise, compare_strong_order_fallback(E, F) is ill-formed[.](#alg-4.4.sentence-1)
|
||
|
||
[*Note [4](#alg-note-4)*:
|
||
|
||
Ill-formed cases above result in substitution failure
|
||
when compare_strong_order_fallback(E, F) appears in the immediate context
|
||
of a template instantiation[.](#alg-4.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[5](#alg-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5636)
|
||
|
||
The name compare_weak_order_fallback denotes
|
||
a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#alg-5.sentence-1)
|
||
|
||
Given subexpressions E and F,
|
||
the expression compare_weak_order_fallback(E, F) is expression-equivalent ([[defns.expression.equivalent]](defns.expression.equivalent "3.22 expression-equivalent")) to:
|
||
|
||
- [(5.1)](#alg-5.1)
|
||
|
||
If the decayed types of E and F differ, compare_weak_order_fallback(E, F) is ill-formed[.](#alg-5.1.sentence-1)
|
||
|
||
- [(5.2)](#alg-5.2)
|
||
|
||
Otherwise, weak_order(E, F) if it is a well-formed expression[.](#alg-5.2.sentence-1)
|
||
|
||
- [(5.3)](#alg-5.3)
|
||
|
||
Otherwise, if the expressions E == F and E < F are both well-formed and
|
||
each of decltype(E == F) and decltype(E < F) models [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"),E == F ? weak_ordering::equivalent : E < F ? weak_ordering::less : weak_ordering::greater except that E and F are evaluated only once[.](#alg-5.3.sentence-1)
|
||
|
||
- [(5.4)](#alg-5.4)
|
||
|
||
Otherwise, compare_weak_order_fallback(E, F) is ill-formed[.](#alg-5.4.sentence-1)
|
||
|
||
[*Note [5](#alg-note-5)*:
|
||
|
||
Ill-formed cases above result in substitution failure
|
||
when compare_weak_order_fallback(E, F) appears in the immediate context
|
||
of a template instantiation[.](#alg-5.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
[6](#alg-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5670)
|
||
|
||
The name compare_partial_order_fallback denotes
|
||
a customization point object ([[customization.point.object]](customization.point.object "16.3.3.3.5 Customization Point Object types"))[.](#alg-6.sentence-1)
|
||
|
||
Given subexpressions E and F,
|
||
the expression compare_partial_order_fallback(E, F) is expression-equivalent ([[defns.expression.equivalent]](defns.expression.equivalent "3.22 expression-equivalent")) to:
|
||
|
||
- [(6.1)](#alg-6.1)
|
||
|
||
If the decayed types of E and F differ, compare_partial_order_fallback(E, F) is ill-formed[.](#alg-6.1.sentence-1)
|
||
|
||
- [(6.2)](#alg-6.2)
|
||
|
||
Otherwise, partial_order(E, F) if it is a well-formed expression[.](#alg-6.2.sentence-1)
|
||
|
||
- [(6.3)](#alg-6.3)
|
||
|
||
Otherwise, if the expressions E == F, E < F, and F < E are all well-formed and
|
||
each of decltype(E == F), decltype(E < F), and decltype(F < E) models [*boolean-testable*](concept.booleantestable#concept:boolean-testable "18.5.2 Boolean testability [concept.booleantestable]"),E == F ? partial_ordering::equivalent : E < F ? partial_ordering::less : F < E ? partial_ordering::greater : partial_ordering::unordered except that E and F are evaluated only once[.](#alg-6.3.sentence-1)
|
||
|
||
- [(6.4)](#alg-6.4)
|
||
|
||
Otherwise, compare_partial_order_fallback(E, F) is ill-formed[.](#alg-6.4.sentence-1)
|
||
|
||
[*Note [6](#alg-note-6)*:
|
||
|
||
Ill-formed cases above result in substitution failure
|
||
when compare_partial_order_fallback(E, F) appears in the immediate context
|
||
of a template instantiation[.](#alg-6.sentence-3)
|
||
|
||
â *end note*]
|
||
|
||
### [17.12.7](#compare.type) Type Ordering [[compare.type]](compare.type)
|
||
|
||
[1](#compare.type-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5708)
|
||
|
||
There is an implementation-defined total ordering of all types[.](#compare.type-1.sentence-1)
|
||
|
||
For any (possibly incomplete) types X and Y,
|
||
the expression *TYPE-ORDER*(X, Y) is a constant expression ([[expr.const]](expr.const "7.7 Constant expressions"))
|
||
of type strong_ordering ([[cmp.strongord]](#strongord "17.12.2.4 Class strong_ordering"))[.](#compare.type-1.sentence-2)
|
||
|
||
Its value is strong_ordering::less if X precedes Y in this implementation-defined total order,strong_ordering::greater if Y precedes X, andstrong_ordering::equal if they are the same type[.](#compare.type-1.sentence-3)
|
||
|
||
[*Note [1](#compare.type-note-1)*:
|
||
|
||
int, const int and int& are different types[.](#compare.type-1.sentence-4)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [2](#compare.type-note-2)*:
|
||
|
||
This ordering need not be consistent with the one induced by type_info::before[.](#compare.type-1.sentence-5)
|
||
|
||
â *end note*]
|
||
|
||
[*Note [3](#compare.type-note-3)*:
|
||
|
||
The ordering of TU-local types from different translation units is not observable,
|
||
because the necessary specialization of type_order is impossible to name[.](#compare.type-1.sentence-6)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:type_order)
|
||
|
||
`template<class T, class U>
|
||
struct type_order;
|
||
`
|
||
|
||
[2](#compare.type-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5735)
|
||
|
||
The name type_order denotes a *Cpp17BinaryTypeTrait* ([[meta.rqmts]](meta.rqmts "21.3.2 Requirements"))
|
||
with a base characteristic ofintegral_constant<strong_ordering, *TYPE-ORDER*(T, U)>[.](#compare.type-2.sentence-1)
|
||
|
||
[3](#compare.type-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/support.tex#L5740)
|
||
|
||
*Recommended practice*: The order should be lexicographical on parameter-type-lists and template argument lists[.](#compare.type-3.sentence-1)
|