tmp/tmpjod96tkh/{from.md → to.md}
RENAMED
|
@@ -26,11 +26,11 @@ namespace std {
|
|
| 26 |
template<class... Ts>
|
| 27 |
struct common_comparison_category {
|
| 28 |
using type = see below;
|
| 29 |
};
|
| 30 |
template<class... Ts>
|
| 31 |
-
using common_comparison_category_t =
|
| 32 |
|
| 33 |
// [cmp.concept], concept three_way_comparable
|
| 34 |
template<class T, class Cat = partial_ordering>
|
| 35 |
concept three_way_comparable = see below;
|
| 36 |
template<class T, class U, class Cat = partial_ordering>
|
|
@@ -38,11 +38,11 @@ namespace std {
|
|
| 38 |
|
| 39 |
// [cmp.result], result of three-way comparison
|
| 40 |
template<class T, class U = T> struct compare_three_way_result;
|
| 41 |
|
| 42 |
template<class T, class U = T>
|
| 43 |
-
using compare_three_way_result_t =
|
| 44 |
|
| 45 |
// [comparisons.three.way], class compare_three_way
|
| 46 |
struct compare_three_way;
|
| 47 |
|
| 48 |
// [cmp.alg], comparison algorithms
|
|
@@ -52,10 +52,17 @@ namespace std {
|
|
| 52 |
inline constexpr unspecified partial_order = unspecified;
|
| 53 |
inline constexpr unspecified compare_strong_order_fallback = unspecified;
|
| 54 |
inline constexpr unspecified compare_weak_order_fallback = unspecified;
|
| 55 |
inline constexpr unspecified compare_partial_order_fallback = unspecified;
|
| 56 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
}
|
| 58 |
```
|
| 59 |
|
| 60 |
### Comparison category types <a id="cmp.categories">[[cmp.categories]]</a>
|
| 61 |
|
|
@@ -89,12 +96,12 @@ meets this requirement.
|
|
| 89 |
— *end example*]
|
| 90 |
|
| 91 |
In this context, the behavior of a program that supplies an argument
|
| 92 |
other than a literal `0` is undefined.
|
| 93 |
|
| 94 |
-
For the purposes of
|
| 95 |
-
|
| 96 |
where `f` denotes a function that reads only comparison-salient state
|
| 97 |
that is accessible via the argument’s public const members.
|
| 98 |
|
| 99 |
#### Class `partial_ordering` <a id="cmp.partialord">[[cmp.partialord]]</a>
|
| 100 |
|
|
@@ -106,17 +113,17 @@ values to be incomparable.[^32]
|
|
| 106 |
|
| 107 |
``` cpp
|
| 108 |
namespace std {
|
| 109 |
class partial_ordering {
|
| 110 |
int value; // exposition only
|
| 111 |
-
bool
|
| 112 |
|
| 113 |
// exposition-only constructors
|
| 114 |
constexpr explicit
|
| 115 |
-
partial_ordering(ord v) noexcept : value(int(v)),
|
| 116 |
constexpr explicit
|
| 117 |
-
partial_ordering(ncmp v) noexcept : value(int(v)),
|
| 118 |
|
| 119 |
public:
|
| 120 |
// valid values
|
| 121 |
static const partial_ordering less;
|
| 122 |
static const partial_ordering equivalent;
|
|
@@ -152,20 +159,20 @@ constexpr bool operator< (partial_ordering v, unspecified) noexcept;
|
|
| 152 |
constexpr bool operator> (partial_ordering v, unspecified) noexcept;
|
| 153 |
constexpr bool operator<=(partial_ordering v, unspecified) noexcept;
|
| 154 |
constexpr bool operator>=(partial_ordering v, unspecified) noexcept;
|
| 155 |
```
|
| 156 |
|
| 157 |
-
*Returns:* For `operator`, `v.
|
| 158 |
|
| 159 |
``` cpp
|
| 160 |
constexpr bool operator< (unspecified, partial_ordering v) noexcept;
|
| 161 |
constexpr bool operator> (unspecified, partial_ordering v) noexcept;
|
| 162 |
constexpr bool operator<=(unspecified, partial_ordering v) noexcept;
|
| 163 |
constexpr bool operator>=(unspecified, partial_ordering v) noexcept;
|
| 164 |
```
|
| 165 |
|
| 166 |
-
*Returns:* For `operator`, `v.
|
| 167 |
|
| 168 |
``` cpp
|
| 169 |
constexpr partial_ordering operator<=>(partial_ordering v, unspecified) noexcept;
|
| 170 |
```
|
| 171 |
|
|
@@ -242,20 +249,20 @@ constexpr bool operator< (weak_ordering v, unspecified) noexcept;
|
|
| 242 |
constexpr bool operator> (weak_ordering v, unspecified) noexcept;
|
| 243 |
constexpr bool operator<=(weak_ordering v, unspecified) noexcept;
|
| 244 |
constexpr bool operator>=(weak_ordering v, unspecified) noexcept;
|
| 245 |
```
|
| 246 |
|
| 247 |
-
*Returns:* `v.value 0` for `operator`.
|
| 248 |
|
| 249 |
``` cpp
|
| 250 |
constexpr bool operator< (unspecified, weak_ordering v) noexcept;
|
| 251 |
constexpr bool operator> (unspecified, weak_ordering v) noexcept;
|
| 252 |
constexpr bool operator<=(unspecified, weak_ordering v) noexcept;
|
| 253 |
constexpr bool operator>=(unspecified, weak_ordering v) noexcept;
|
| 254 |
```
|
| 255 |
|
| 256 |
-
*Returns:* `0 v.value` for `operator`.
|
| 257 |
|
| 258 |
``` cpp
|
| 259 |
constexpr weak_ordering operator<=>(weak_ordering v, unspecified) noexcept;
|
| 260 |
```
|
| 261 |
|
|
@@ -347,20 +354,20 @@ constexpr bool operator< (strong_ordering v, unspecified) noexcept;
|
|
| 347 |
constexpr bool operator> (strong_ordering v, unspecified) noexcept;
|
| 348 |
constexpr bool operator<=(strong_ordering v, unspecified) noexcept;
|
| 349 |
constexpr bool operator>=(strong_ordering v, unspecified) noexcept;
|
| 350 |
```
|
| 351 |
|
| 352 |
-
*Returns:* `v.value 0` for `operator`.
|
| 353 |
|
| 354 |
``` cpp
|
| 355 |
constexpr bool operator< (unspecified, strong_ordering v) noexcept;
|
| 356 |
constexpr bool operator> (unspecified, strong_ordering v) noexcept;
|
| 357 |
constexpr bool operator<=(unspecified, strong_ordering v) noexcept;
|
| 358 |
constexpr bool operator>=(unspecified, strong_ordering v) noexcept;
|
| 359 |
```
|
| 360 |
|
| 361 |
-
*Returns:* `0 v.value` for `operator`.
|
| 362 |
|
| 363 |
``` cpp
|
| 364 |
constexpr strong_ordering operator<=>(strong_ordering v, unspecified) noexcept;
|
| 365 |
```
|
| 366 |
|
|
@@ -419,14 +426,14 @@ template<class T, class U>
|
|
| 419 |
};
|
| 420 |
```
|
| 421 |
|
| 422 |
Let `t` and `u` be lvalues of types `const remove_reference_t<T>` and
|
| 423 |
`const remove_reference_t<U>`, respectively. `T` and `U` model
|
| 424 |
-
`partially-ordered-with<T, U>` only if
|
| 425 |
|
| 426 |
- `t < u`, `t <= u`, `t > u`, `t >= u`, `u < t`, `u <= t`, `u > t`, and
|
| 427 |
-
`u >= t` have the same domain
|
| 428 |
- `bool(t < u) == bool(u > t)` is `true`,
|
| 429 |
- `bool(u < t) == bool(t > u)` is `true`,
|
| 430 |
- `bool(t <= u) == bool(u >= t)` is `true`, and
|
| 431 |
- `bool(u <= t) == bool(t >= u)` is `true`.
|
| 432 |
|
|
@@ -439,11 +446,11 @@ template<class T, class Cat = partial_ordering>
|
|
| 439 |
{ a <=> b } -> compares-as<Cat>;
|
| 440 |
};
|
| 441 |
```
|
| 442 |
|
| 443 |
Let `a` and `b` be lvalues of type `const remove_reference_t<T>`. `T`
|
| 444 |
-
and `Cat` model `three_way_comparable<T, Cat>` only if
|
| 445 |
|
| 446 |
- `(a <=> b == 0) == bool(a == b)` is `true`,
|
| 447 |
- `(a <=> b != 0) == bool(a != b)` is `true`,
|
| 448 |
- `((a <=> b) <=> 0)` and `(0 <=> (b <=> a))` are equal,
|
| 449 |
- `(a <=> b < 0) == bool(a < b)` is `true`,
|
|
@@ -475,11 +482,11 @@ let `u` and `u2` be lvalues denoting distinct equal objects of types
|
|
| 475 |
`const remove_reference_t<U>` and `remove_cvref_t<U>`, respectively. Let
|
| 476 |
`C` be
|
| 477 |
`common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>`.
|
| 478 |
Let `CONVERT_TO_LVALUE<C>(E)` be defined as in
|
| 479 |
[[concepts.compare.general]]. `T`, `U`, and `Cat` model
|
| 480 |
-
`three_way_comparable_with<T, U, Cat>` only if
|
| 481 |
|
| 482 |
- `t <=> u` and `u <=> t` have the same domain,
|
| 483 |
- `((t <=> u) <=> 0)` and `(0 <=> (u <=> t))` are equal,
|
| 484 |
- `(t <=> u == 0) == bool(t == u)` is `true`,
|
| 485 |
- `(t <=> u != 0) == bool(t != u)` is `true`,
|
|
@@ -521,11 +528,11 @@ expression `strong_order(E, F)` is expression-equivalent
|
|
| 521 |
[[basic.lookup.argdep]].
|
| 522 |
- Otherwise, if the decayed type `T` of `E` is a floating-point type,
|
| 523 |
yields a value of type `strong_ordering` that is consistent with the
|
| 524 |
ordering observed by `T`’s comparison operators, and if
|
| 525 |
`numeric_limits<T>::is_iec559` is `true`, is additionally consistent
|
| 526 |
-
with the `totalOrder` operation as specified in ISO/IEC
|
| 527 |
- Otherwise, `strong_ordering(compare_three_way()(E, F))` if it is a
|
| 528 |
well-formed expression.
|
| 529 |
- Otherwise, `strong_order(E, F)` is ill-formed.
|
| 530 |
|
| 531 |
[*Note 1*: Ill-formed cases above result in substitution failure when
|
|
@@ -643,12 +650,12 @@ expression-equivalent [[defns.expression.equivalent]] to:
|
|
| 643 |
|
| 644 |
- If the decayed types of `E` and `F` differ,
|
| 645 |
`compare_partial_order_fallback(E, F)` is ill-formed.
|
| 646 |
- Otherwise, `partial_order(E, F)` if it is a well-formed expression.
|
| 647 |
- Otherwise, if the expressions `E == F`, `E < F`, and `F < E` are all
|
| 648 |
-
well-formed and each of `decltype(E == F)`
|
| 649 |
-
models `boolean-testable`,
|
| 650 |
``` cpp
|
| 651 |
E == F ? partial_ordering::equivalent :
|
| 652 |
E < F ? partial_ordering::less :
|
| 653 |
F < E ? partial_ordering::greater :
|
| 654 |
partial_ordering::unordered
|
|
@@ -659,5 +666,37 @@ expression-equivalent [[defns.expression.equivalent]] to:
|
|
| 659 |
|
| 660 |
[*Note 6*: Ill-formed cases above result in substitution failure when
|
| 661 |
`compare_partial_order_fallback(E, F)` appears in the immediate context
|
| 662 |
of a template instantiation. — *end note*]
|
| 663 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
template<class... Ts>
|
| 27 |
struct common_comparison_category {
|
| 28 |
using type = see below;
|
| 29 |
};
|
| 30 |
template<class... Ts>
|
| 31 |
+
using common_comparison_category_t = common_comparison_category<Ts...>::type;
|
| 32 |
|
| 33 |
// [cmp.concept], concept three_way_comparable
|
| 34 |
template<class T, class Cat = partial_ordering>
|
| 35 |
concept three_way_comparable = see below;
|
| 36 |
template<class T, class U, class Cat = partial_ordering>
|
|
|
|
| 38 |
|
| 39 |
// [cmp.result], result of three-way comparison
|
| 40 |
template<class T, class U = T> struct compare_three_way_result;
|
| 41 |
|
| 42 |
template<class T, class U = T>
|
| 43 |
+
using compare_three_way_result_t = compare_three_way_result<T, U>::type;
|
| 44 |
|
| 45 |
// [comparisons.three.way], class compare_three_way
|
| 46 |
struct compare_three_way;
|
| 47 |
|
| 48 |
// [cmp.alg], comparison algorithms
|
|
|
|
| 52 |
inline constexpr unspecified partial_order = unspecified;
|
| 53 |
inline constexpr unspecified compare_strong_order_fallback = unspecified;
|
| 54 |
inline constexpr unspecified compare_weak_order_fallback = unspecified;
|
| 55 |
inline constexpr unspecified compare_partial_order_fallback = unspecified;
|
| 56 |
}
|
| 57 |
+
|
| 58 |
+
// [compare.type], type ordering
|
| 59 |
+
template<class T, class U>
|
| 60 |
+
struct type_order;
|
| 61 |
+
|
| 62 |
+
template<class T, class U>
|
| 63 |
+
constexpr strong_ordering type_order_v = type_order<T, U>::value;
|
| 64 |
}
|
| 65 |
```
|
| 66 |
|
| 67 |
### Comparison category types <a id="cmp.categories">[[cmp.categories]]</a>
|
| 68 |
|
|
|
|
| 96 |
— *end example*]
|
| 97 |
|
| 98 |
In this context, the behavior of a program that supplies an argument
|
| 99 |
other than a literal `0` is undefined.
|
| 100 |
|
| 101 |
+
For the purposes of [[cmp.categories]], *substitutability* is the
|
| 102 |
+
property that `f(a) == f(b)` is `true` whenever `a == b` is `true`,
|
| 103 |
where `f` denotes a function that reads only comparison-salient state
|
| 104 |
that is accessible via the argument’s public const members.
|
| 105 |
|
| 106 |
#### Class `partial_ordering` <a id="cmp.partialord">[[cmp.partialord]]</a>
|
| 107 |
|
|
|
|
| 113 |
|
| 114 |
``` cpp
|
| 115 |
namespace std {
|
| 116 |
class partial_ordering {
|
| 117 |
int value; // exposition only
|
| 118 |
+
bool is-ordered; // exposition only
|
| 119 |
|
| 120 |
// exposition-only constructors
|
| 121 |
constexpr explicit
|
| 122 |
+
partial_ordering(ord v) noexcept : value(int(v)), is-ordered(true) {} // exposition only
|
| 123 |
constexpr explicit
|
| 124 |
+
partial_ordering(ncmp v) noexcept : value(int(v)), is-ordered(false) {} // exposition only
|
| 125 |
|
| 126 |
public:
|
| 127 |
// valid values
|
| 128 |
static const partial_ordering less;
|
| 129 |
static const partial_ordering equivalent;
|
|
|
|
| 159 |
constexpr bool operator> (partial_ordering v, unspecified) noexcept;
|
| 160 |
constexpr bool operator<=(partial_ordering v, unspecified) noexcept;
|
| 161 |
constexpr bool operator>=(partial_ordering v, unspecified) noexcept;
|
| 162 |
```
|
| 163 |
|
| 164 |
+
*Returns:* For `operator`, `v.`*`is-ordered`*` && v.`*`value`*` 0`.
|
| 165 |
|
| 166 |
``` cpp
|
| 167 |
constexpr bool operator< (unspecified, partial_ordering v) noexcept;
|
| 168 |
constexpr bool operator> (unspecified, partial_ordering v) noexcept;
|
| 169 |
constexpr bool operator<=(unspecified, partial_ordering v) noexcept;
|
| 170 |
constexpr bool operator>=(unspecified, partial_ordering v) noexcept;
|
| 171 |
```
|
| 172 |
|
| 173 |
+
*Returns:* For `operator`, `v.`*`is-ordered`*` && 0 v.`*`value`*.
|
| 174 |
|
| 175 |
``` cpp
|
| 176 |
constexpr partial_ordering operator<=>(partial_ordering v, unspecified) noexcept;
|
| 177 |
```
|
| 178 |
|
|
|
|
| 249 |
constexpr bool operator> (weak_ordering v, unspecified) noexcept;
|
| 250 |
constexpr bool operator<=(weak_ordering v, unspecified) noexcept;
|
| 251 |
constexpr bool operator>=(weak_ordering v, unspecified) noexcept;
|
| 252 |
```
|
| 253 |
|
| 254 |
+
*Returns:* `v.`*`value`*` 0` for `operator`.
|
| 255 |
|
| 256 |
``` cpp
|
| 257 |
constexpr bool operator< (unspecified, weak_ordering v) noexcept;
|
| 258 |
constexpr bool operator> (unspecified, weak_ordering v) noexcept;
|
| 259 |
constexpr bool operator<=(unspecified, weak_ordering v) noexcept;
|
| 260 |
constexpr bool operator>=(unspecified, weak_ordering v) noexcept;
|
| 261 |
```
|
| 262 |
|
| 263 |
+
*Returns:* `0 v.`*`value`* for `operator`.
|
| 264 |
|
| 265 |
``` cpp
|
| 266 |
constexpr weak_ordering operator<=>(weak_ordering v, unspecified) noexcept;
|
| 267 |
```
|
| 268 |
|
|
|
|
| 354 |
constexpr bool operator> (strong_ordering v, unspecified) noexcept;
|
| 355 |
constexpr bool operator<=(strong_ordering v, unspecified) noexcept;
|
| 356 |
constexpr bool operator>=(strong_ordering v, unspecified) noexcept;
|
| 357 |
```
|
| 358 |
|
| 359 |
+
*Returns:* `v.`*`value`*` 0` for `operator`.
|
| 360 |
|
| 361 |
``` cpp
|
| 362 |
constexpr bool operator< (unspecified, strong_ordering v) noexcept;
|
| 363 |
constexpr bool operator> (unspecified, strong_ordering v) noexcept;
|
| 364 |
constexpr bool operator<=(unspecified, strong_ordering v) noexcept;
|
| 365 |
constexpr bool operator>=(unspecified, strong_ordering v) noexcept;
|
| 366 |
```
|
| 367 |
|
| 368 |
+
*Returns:* `0 v.`*`value`* for `operator`.
|
| 369 |
|
| 370 |
``` cpp
|
| 371 |
constexpr strong_ordering operator<=>(strong_ordering v, unspecified) noexcept;
|
| 372 |
```
|
| 373 |
|
|
|
|
| 426 |
};
|
| 427 |
```
|
| 428 |
|
| 429 |
Let `t` and `u` be lvalues of types `const remove_reference_t<T>` and
|
| 430 |
`const remove_reference_t<U>`, respectively. `T` and `U` model
|
| 431 |
+
`partially-ordered-with<T, U>` only if
|
| 432 |
|
| 433 |
- `t < u`, `t <= u`, `t > u`, `t >= u`, `u < t`, `u <= t`, `u > t`, and
|
| 434 |
+
`u >= t` have the same domain,
|
| 435 |
- `bool(t < u) == bool(u > t)` is `true`,
|
| 436 |
- `bool(u < t) == bool(t > u)` is `true`,
|
| 437 |
- `bool(t <= u) == bool(u >= t)` is `true`, and
|
| 438 |
- `bool(u <= t) == bool(t >= u)` is `true`.
|
| 439 |
|
|
|
|
| 446 |
{ a <=> b } -> compares-as<Cat>;
|
| 447 |
};
|
| 448 |
```
|
| 449 |
|
| 450 |
Let `a` and `b` be lvalues of type `const remove_reference_t<T>`. `T`
|
| 451 |
+
and `Cat` model `three_way_comparable<T, Cat>` only if
|
| 452 |
|
| 453 |
- `(a <=> b == 0) == bool(a == b)` is `true`,
|
| 454 |
- `(a <=> b != 0) == bool(a != b)` is `true`,
|
| 455 |
- `((a <=> b) <=> 0)` and `(0 <=> (b <=> a))` are equal,
|
| 456 |
- `(a <=> b < 0) == bool(a < b)` is `true`,
|
|
|
|
| 482 |
`const remove_reference_t<U>` and `remove_cvref_t<U>`, respectively. Let
|
| 483 |
`C` be
|
| 484 |
`common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>`.
|
| 485 |
Let `CONVERT_TO_LVALUE<C>(E)` be defined as in
|
| 486 |
[[concepts.compare.general]]. `T`, `U`, and `Cat` model
|
| 487 |
+
`three_way_comparable_with<T, U, Cat>` only if
|
| 488 |
|
| 489 |
- `t <=> u` and `u <=> t` have the same domain,
|
| 490 |
- `((t <=> u) <=> 0)` and `(0 <=> (u <=> t))` are equal,
|
| 491 |
- `(t <=> u == 0) == bool(t == u)` is `true`,
|
| 492 |
- `(t <=> u != 0) == bool(t != u)` is `true`,
|
|
|
|
| 528 |
[[basic.lookup.argdep]].
|
| 529 |
- Otherwise, if the decayed type `T` of `E` is a floating-point type,
|
| 530 |
yields a value of type `strong_ordering` that is consistent with the
|
| 531 |
ordering observed by `T`’s comparison operators, and if
|
| 532 |
`numeric_limits<T>::is_iec559` is `true`, is additionally consistent
|
| 533 |
+
with the `totalOrder` operation as specified in ISO/IEC 60559.
|
| 534 |
- Otherwise, `strong_ordering(compare_three_way()(E, F))` if it is a
|
| 535 |
well-formed expression.
|
| 536 |
- Otherwise, `strong_order(E, F)` is ill-formed.
|
| 537 |
|
| 538 |
[*Note 1*: Ill-formed cases above result in substitution failure when
|
|
|
|
| 650 |
|
| 651 |
- If the decayed types of `E` and `F` differ,
|
| 652 |
`compare_partial_order_fallback(E, F)` is ill-formed.
|
| 653 |
- Otherwise, `partial_order(E, F)` if it is a well-formed expression.
|
| 654 |
- Otherwise, if the expressions `E == F`, `E < F`, and `F < E` are all
|
| 655 |
+
well-formed and each of `decltype(E == F)`, `decltype(E < F)`, and
|
| 656 |
+
`decltype(F < E)` models `boolean-testable`,
|
| 657 |
``` cpp
|
| 658 |
E == F ? partial_ordering::equivalent :
|
| 659 |
E < F ? partial_ordering::less :
|
| 660 |
F < E ? partial_ordering::greater :
|
| 661 |
partial_ordering::unordered
|
|
|
|
| 666 |
|
| 667 |
[*Note 6*: Ill-formed cases above result in substitution failure when
|
| 668 |
`compare_partial_order_fallback(E, F)` appears in the immediate context
|
| 669 |
of a template instantiation. — *end note*]
|
| 670 |
|
| 671 |
+
### Type Ordering <a id="compare.type">[[compare.type]]</a>
|
| 672 |
+
|
| 673 |
+
There is an *implementation-defined* total ordering of all types. For
|
| 674 |
+
any (possibly incomplete) types `X` and `Y`, the expression
|
| 675 |
+
`TYPE-ORDER(X, Y)` is a constant expression [[expr.const]] of type
|
| 676 |
+
`strong_ordering` [[cmp.strongord]]. Its value is
|
| 677 |
+
`strong_ordering::less` if `X` precedes `Y` in this
|
| 678 |
+
implementation-defined total order, `strong_ordering::greater` if `Y`
|
| 679 |
+
precedes `X`, and `strong_ordering::equal` if they are the same type.
|
| 680 |
+
|
| 681 |
+
[*Note 1*: `int`, `const int` and `int&` are different
|
| 682 |
+
types. — *end note*]
|
| 683 |
+
|
| 684 |
+
[*Note 2*: This ordering need not be consistent with the one induced by
|
| 685 |
+
`type_info::before`. — *end note*]
|
| 686 |
+
|
| 687 |
+
[*Note 3*: The ordering of TU-local types from different translation
|
| 688 |
+
units is not observable, because the necessary specialization of
|
| 689 |
+
`type_order` is impossible to name. — *end note*]
|
| 690 |
+
|
| 691 |
+
``` cpp
|
| 692 |
+
template<class T, class U>
|
| 693 |
+
struct type_order;
|
| 694 |
+
```
|
| 695 |
+
|
| 696 |
+
The name `type_order` denotes a *Cpp17BinaryTypeTrait*[[meta.rqmts]]
|
| 697 |
+
with a base characteristic of
|
| 698 |
+
`integral_constant<strong_ordering, `*`TYPE-ORDER`*`(T, U)>`.
|
| 699 |
+
|
| 700 |
+
*Recommended practice:* The order should be lexicographical on
|
| 701 |
+
parameter-type-lists and template argument lists.
|
| 702 |
+
|