diff --git a/source/algorithms.tex b/source/algorithms.tex index 7d42b90c67..7133983702 100644 --- a/source/algorithms.tex +++ b/source/algorithms.tex @@ -2830,19 +2830,17 @@ Proj1 proj1 = {}, Proj2 proj2 = {}); } - // \ref{alg.3way}, three-way comparison algorithms - template - constexpr auto compare_3way(const T& a, const U& b); + // \ref{alg.three.way}, three-way comparison algorithms template constexpr auto - lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1, - InputIterator2 b2, InputIterator2 e2, - Cmp comp) + lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, + InputIterator2 b2, InputIterator2 e2, + Cmp comp) -> common_comparison_category_t; template constexpr auto - lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1, - InputIterator2 b2, InputIterator2 e2); + lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, + InputIterator2 b2, InputIterator2 e2); // \ref{alg.permutation.generators}, permutations template @@ -8367,46 +8365,15 @@ \end{note} \end{itemdescr} -\rSec2[alg.3way]{Three-way comparison algorithms} +\rSec2[alg.three.way]{Three-way comparison algorithms} -\indexlibrary{\idxcode{compare_3way}}% -\begin{itemdecl} -template constexpr auto compare_3way(const T& a, const U& b); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects -Compares two values and produces a result -of the strongest applicable comparison category type: -\begin{itemize} -\item - Returns \tcode{a <=> b} if that expression is well-formed. -\item - Otherwise, if the expressions \tcode{a == b} and \tcode{a < b} - are each well-formed and convertible to \tcode{bool}, - returns \tcode{strong_ordering::equal} - when \tcode{a == b} is \tcode{true}, - otherwise returns \tcode{strong_ordering::less} - when \tcode{a < b} is \tcode{true}, - and otherwise returns \tcode{strong_ordering::greater}. -\item - Otherwise, if the expression \tcode{a == b} - is well-formed and convertible to \tcode{bool}, - returns \tcode{strong_equality::equal} when \tcode{a == b} is \tcode{true}, - and otherwise returns \tcode{strong_equality::nonequal}. -\item - Otherwise, the function is defined as deleted. -\end{itemize} -\end{itemdescr} - -\indexlibrary{\idxcode{lexicographical_compare_3way}}% +\indexlibrary{\idxcode{lexicographical_compare_three_way}}% \begin{itemdecl} template constexpr auto - lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1, - InputIterator2 b2, InputIterator2 e2, - Cmp comp) + lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, + InputIterator2 b2, InputIterator2 e2, + Cmp comp) -> common_comparison_category_t; \end{itemdecl} @@ -8431,12 +8398,12 @@ \end{codeblock} \end{itemdescr} -\indexlibrary{\idxcode{lexicographical_compare_3way}}% +\indexlibrary{\idxcode{lexicographical_compare_three_way}}% \begin{itemdecl} template constexpr auto - lexicographical_compare_3way(InputIterator1 b1, InputIterator1 e1, - InputIterator2 b2, InputIterator2 e2); + lexicographical_compare_three_way(InputIterator1 b1, InputIterator1 e1, + InputIterator2 b2, InputIterator2 e2); \end{itemdecl} \begin{itemdescr} @@ -8444,10 +8411,7 @@ \effects Equivalent to: \begin{codeblock} -return lexicographical_compare_3way(b1, e1, b2, e2, - [](const auto& t, const auto& u) { - return compare_3way(t, u); - }); +return lexicographical_compare_three_way(b1, e1, b2, e2, compare_three_way()); \end{codeblock} \end{itemdescr} diff --git a/source/containers.tex b/source/containers.tex index b1f99b0770..f414d3249b 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -71,12 +71,12 @@ In Tables~\ref{tab:container.req}, \ref{tab:container.rev.req}, and \ref{tab:container.opt} -\tcode{X} denotes a container class containing objects of type -\tcode{T}, \tcode{a} and \tcode{b} -denote values of type \tcode{X}, \tcode{u} -denotes an identifier, \tcode{r} denotes -a non-const value of type \tcode{X}, and \tcode{rv} -denotes a non-const rvalue of type \tcode{X}. +\tcode{X} denotes a container class containing objects of type \tcode{T}, +\tcode{a} and \tcode{b} denote values of type \tcode{X}, +\tcode{i} and \tcode{j} denote values of type (possibly const) \tcode{X::iterator}, +\tcode{u} denotes an identifier, +\tcode{r} denotes a non-const value of type \tcode{X}, and +\tcode{rv} denotes a non-const rvalue of type \tcode{X}. \begin{libreqtab5} {Container requirements} @@ -211,6 +211,14 @@ & constant \\ \rowsep +\tcode{i <=> j} & + \tcode{strong_ordering} + if \tcode{X::iterator} meets the random access iterator requirements, + otherwise \tcode{strong_equality} & + & + & + constant \\ \rowsep + \tcode{a == b} & convertible to \tcode{bool} & \tcode{==} is an equivalence relation. @@ -293,6 +301,7 @@ i <= j i >= j i > j +i <=> j i - j \end{codeblock} where \tcode{i} and \tcode{j} denote objects of a container's \tcode{iterator} @@ -463,7 +472,7 @@ for some types of containers but not others. Those containers for which the listed operations are provided shall implement the semantics described in \tref{container.opt} unless otherwise stated. -If the iterators passed to \tcode{lexicographical_compare} +If the iterators passed to \tcode{lexicographical_compare_three_way} meet the constexpr iterator requirements\iref{iterator.requirements.general} then the operations described in \tref{container.opt} are implemented by constexpr functions. @@ -483,33 +492,20 @@ & & \chdr{semantics} & \chdr{pre-/post-condition} & \\ \capsep \endhead -\tcode{a < b} & - convertible to \tcode{bool} & - \tcode{lexicographical_compare( a.begin(), a.end(), b.begin(), b.end())} & - \expects \tcode{<} is defined for values of type (possibly \tcode{const}) \tcode{T}. \tcode{<} is a total ordering relationship. & - linear \\ \rowsep - -\tcode{a > b} & - convertible to \tcode{bool} & - \tcode{b < a} & - & - linear \\ \rowsep - -\tcode{a <= b} & - convertible to \tcode{bool} & - \tcode{!(a > b)} & - & - linear \\ \rowsep - -\tcode{a >= b} & - convertible to \tcode{bool} & - \tcode{!(a < b)} & - & +\tcode{a <=> b} & + \tcode{\placeholdernc{synth-three-\brk{}way-result}\brk{}} & + \tcode{lexicographical_compare_three_way(a.begin(), a.end(), + b.begin(), b.end(), \placeholdernc{synth-three-way})} & + \expects + Either \tcode{<=>} is defined for values of type (possibly const) \tcode{T}, + or \tcode{<} is defined for values of type (possibly const) \tcode{T} and + \tcode{<} is a total ordering relationship. & linear \\ \end{libreqtab5} \begin{note} -The algorithm \tcode{lexicographical_compare()} is defined in \ref{algorithms}. +The algorithm \tcode{lexicographical_compare_three_way} +is defined in \ref{algorithms}. \end{note} \pnum @@ -3149,18 +3145,6 @@ // \ref{array}, class template \tcode{array} template struct array; - template - constexpr bool operator==(const array& x, const array& y); - template - constexpr bool operator!=(const array& x, const array& y); - template - constexpr bool operator< (const array& x, const array& y); - template - constexpr bool operator> (const array& x, const array& y); - template - constexpr bool operator<=(const array& x, const array& y); - template - constexpr bool operator>=(const array& x, const array& y); template constexpr void swap(array& x, array& y) noexcept(noexcept(x.swap(y))); @@ -3196,15 +3180,8 @@ template bool operator==(const deque& x, const deque& y); template - bool operator!=(const deque& x, const deque& y); - template - bool operator< (const deque& x, const deque& y); - template - bool operator> (const deque& x, const deque& y); - template - bool operator<=(const deque& x, const deque& y); - template - bool operator>=(const deque& x, const deque& y); + @\placeholder{synth-three-way-result}@ operator<=>(const deque& x, + @\itcorr@ const deque& y); template void swap(deque& x, deque& y) @@ -3236,15 +3213,8 @@ template bool operator==(const forward_list& x, const forward_list& y); template - bool operator!=(const forward_list& x, const forward_list& y); - template - bool operator< (const forward_list& x, const forward_list& y); - template - bool operator> (const forward_list& x, const forward_list& y); - template - bool operator<=(const forward_list& x, const forward_list& y); - template - bool operator>=(const forward_list& x, const forward_list& y); + @\placeholder{synth-three-way-result}@ operator<=>(const forward_list& x, + @\itcorr@ const forward_list& y); template void swap(forward_list& x, forward_list& y) @@ -3276,15 +3246,8 @@ template bool operator==(const list& x, const list& y); template - bool operator!=(const list& x, const list& y); - template - bool operator< (const list& x, const list& y); - template - bool operator> (const list& x, const list& y); - template - bool operator<=(const list& x, const list& y); - template - bool operator>=(const list& x, const list& y); + @\placeholder{synth-three-way-result}@ operator<=>(const list& x, + @\itcorr@ const list& y); template void swap(list& x, list& y) @@ -3316,15 +3279,8 @@ template bool operator==(const vector& x, const vector& y); template - bool operator!=(const vector& x, const vector& y); - template - bool operator< (const vector& x, const vector& y); - template - bool operator> (const vector& x, const vector& y); - template - bool operator<=(const vector& x, const vector& y); - template - bool operator>=(const vector& x, const vector& y); + @\placeholder{synth-three-way-result}@ operator<=>(const vector& x, + @\itcorr@ const vector& y); template void swap(vector& x, vector& y) @@ -3445,6 +3401,10 @@ constexpr T * data() noexcept; constexpr const T * data() const noexcept; + + friend constexpr bool operator==(const array&, const array&) = default; + friend constexpr @\placeholder{synth-three-way-result}@ + operator<=>(const array&, const array&); }; template @@ -6138,20 +6098,9 @@ bool operator==(const map& x, const map& y); template - bool operator!=(const map& x, - const map& y); - template - bool operator< (const map& x, - const map& y); - template - bool operator> (const map& x, - const map& y); - template - bool operator<=(const map& x, - const map& y); - template - bool operator>=(const map& x, - const map& y); + @\placeholder{synth-three-way-result}@> + operator<=>(const map& x, + const map& y); template void swap(map& x, @@ -6170,20 +6119,9 @@ bool operator==(const multimap& x, const multimap& y); template - bool operator!=(const multimap& x, - const multimap& y); - template - bool operator< (const multimap& x, - const multimap& y); - template - bool operator> (const multimap& x, - const multimap& y); - template - bool operator<=(const multimap& x, - const multimap& y); - template - bool operator>=(const multimap& x, - const multimap& y); + @\placeholder{synth-three-way-result}@> + operator<=>(const multimap& x, + const multimap& y); template void swap(multimap& x, @@ -6221,20 +6159,8 @@ bool operator==(const set& x, const set& y); template - bool operator!=(const set& x, - const set& y); - template - bool operator< (const set& x, - const set& y); - template - bool operator> (const set& x, - const set& y); - template - bool operator<=(const set& x, - const set& y); - template - bool operator>=(const set& x, - const set& y); + @\placeholder{synth-three-way-result}@ operator<=>(const set& x, + @\itcorr@ const set& y); template void swap(set& x, @@ -6252,20 +6178,8 @@ bool operator==(const multiset& x, const multiset& y); template - bool operator!=(const multiset& x, - const multiset& y); - template - bool operator< (const multiset& x, - const multiset& y); - template - bool operator> (const multiset& x, - const multiset& y); - template - bool operator<=(const multiset& x, - const multiset& y); - template - bool operator>=(const multiset& x, - const multiset& y); + @\placeholder{synth-three-way-result}@ operator<=>(const multiset& x, + @\itcorr@ const multiset& y); template void swap(multiset& x, @@ -7749,16 +7663,10 @@ template bool operator==(const unordered_map& a, const unordered_map& b); - template - bool operator!=(const unordered_map& a, - const unordered_map& b); template bool operator==(const unordered_multimap& a, const unordered_multimap& b); - template - bool operator!=(const unordered_multimap& a, - const unordered_multimap& b); template void swap(unordered_map& x, @@ -7821,16 +7729,10 @@ template bool operator==(const unordered_set& a, const unordered_set& b); - template - bool operator!=(const unordered_set& a, - const unordered_set& b); template bool operator==(const unordered_multiset& a, const unordered_multiset& b); - template - bool operator!=(const unordered_multiset& a, - const unordered_multiset& b); template void swap(unordered_set& x, @@ -9583,6 +9485,9 @@ bool operator<=(const queue& x, const queue& y); template bool operator>=(const queue& x, const queue& y); + template + compare_three_way_result_t + operator<=>(const queue& x, const queue& y); template void swap(queue& x, queue& y) noexcept(noexcept(x.swap(y))); @@ -9622,6 +9527,9 @@ bool operator<=(const stack& x, const stack& y); template bool operator>=(const stack& x, const stack& y); + template + compare_three_way_result_t + operator<=>(const stack& x, const stack& y); template void swap(stack& x, stack& y) noexcept(noexcept(x.swap(y))); @@ -9855,6 +9763,19 @@ \tcode{x.c >= y.c}. \end{itemdescr} +\indexlibrary{\idxcode{operator<=>}!\idxcode{queue}}% +\begin{itemdecl} +template + compare_three_way_result_t + operator<=>(const queue& x, const queue& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.c <=> y.c}. +\end{itemdescr} + \rSec3[queue.special]{Specialized algorithms} \indexlibrarymember{swap}{queue}% @@ -10402,6 +10323,19 @@ \tcode{x.c >= y.c}. \end{itemdescr} +\indexlibrary{\idxcode{operator<=>}!\idxcode{stack}}% +\begin{itemdecl} +template + compare_three_way_result_t + operator<=>(const stack& x, const stack& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.c <=> y.c}. +\end{itemdescr} + \rSec3[stack.special]{Specialized algorithms} \indexlibrarymember{swap}{stack}% diff --git a/source/diagnostics.tex b/source/diagnostics.tex index 63dfcbd9d2..8ef0376b6d 100644 --- a/source/diagnostics.tex +++ b/source/diagnostics.tex @@ -799,14 +799,9 @@ // \ref{syserr.compare}, comparison functions bool operator==(const error_code& lhs, const error_code& rhs) noexcept; bool operator==(const error_code& lhs, const error_condition& rhs) noexcept; - bool operator==(const error_condition& lhs, const error_code& rhs) noexcept; bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept; - bool operator!=(const error_code& lhs, const error_code& rhs) noexcept; - bool operator!=(const error_code& lhs, const error_condition& rhs) noexcept; - bool operator!=(const error_condition& lhs, const error_code& rhs) noexcept; - bool operator!=(const error_condition& lhs, const error_condition& rhs) noexcept; - bool operator< (const error_code& lhs, const error_code& rhs) noexcept; - bool operator< (const error_condition& lhs, const error_condition& rhs) noexcept; + strong_ordering operator<=>(const error_code& lhs, const error_code& rhs) noexcept; + strong_ordering operator<=>(const error_condition& lhs, const error_condition& rhs) noexcept; // \ref{syserr.hash}, hash support template struct hash; @@ -868,8 +863,7 @@ virtual string message(int ev) const = 0; bool operator==(const error_category& rhs) const noexcept; - bool operator!=(const error_category& rhs) const noexcept; - bool operator< (const error_category& rhs) const noexcept; + strong_ordering operator<=>(const error_category& rhs) const noexcept; }; const error_category& generic_category() noexcept; @@ -942,26 +936,18 @@ \returns \tcode{this == \&rhs}. \end{itemdescr} -\indexlibrarymember{operator"!=}{error_category}% +\indexlibrarymember{operator<=>}{error_category}% \begin{itemdecl} -bool operator!=(const error_category& rhs) const noexcept; +strong_ordering operator<=>(const error_category& rhs) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{!(*this == rhs)}. -\end{itemdescr} - -\indexlibrarymember{operator<}{error_category}% -\begin{itemdecl} -bool operator<(const error_category& rhs) const noexcept; -\end{itemdecl} +\returns \tcode{compare_three_way()(this, \&rhs)}. -\begin{itemdescr} -\pnum -\returns \tcode{less()(this, \&rhs)}. - -\begin{note} \tcode{less}\iref{comparisons} provides a total ordering for pointers. \end{note} +\begin{note} +\tcode{compare_three_way}\iref{cmp.object} provides a total ordering for pointers. +\end{note} \end{itemdescr} \rSec3[syserr.errcat.derived]{Program-defined classes derived from \tcode{error_category}} @@ -1446,20 +1432,6 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator==}{error_condition}% -\indexlibrarymember{operator==}{error_code}% -\begin{itemdecl} -bool operator==(const error_condition& lhs, const error_code& rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\begin{codeblock} -rhs.category().equivalent(rhs.value(), lhs) || lhs.category().equivalent(rhs, lhs.value()) -\end{codeblock} -\end{itemdescr} - \indexlibrarymember{operator==}{error_condition}% \begin{itemdecl} bool operator==(const error_condition& lhs, const error_condition& rhs) noexcept; @@ -1473,45 +1445,32 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator"!=}{error_code}% -\indexlibrarymember{operator"!=}{error_condition}% +\indexlibrarymember{operator<=>}{error_code}% \begin{itemdecl} -bool operator!=(const error_code& lhs, const error_code& rhs) noexcept; -bool operator!=(const error_code& lhs, const error_condition& rhs) noexcept; -bool operator!=(const error_condition& lhs, const error_code& rhs) noexcept; -bool operator!=(const error_condition& lhs, const error_condition& rhs) noexcept; +strong_ordering operator<=>(const error_code& lhs, const error_code& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{!(lhs == rhs)}. -\end{itemdescr} - -\indexlibrarymember{operator<}{error_code}% -\begin{itemdecl} -bool operator<(const error_code& lhs, const error_code& rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns +\effects +Equivalent to: \begin{codeblock} -lhs.category() < rhs.category() || -(lhs.category() == rhs.category() && lhs.value() < rhs.value()) +if (auto c = lhs.category() <=> rhs.category(); c != 0) return c; +return lhs.value() <=> rhs.value(); \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator<}{error_condition}% +\indexlibrarymember{operator<=>}{error_condition}% \begin{itemdecl} -bool operator<(const error_condition& lhs, const error_condition& rhs) noexcept; +strong_ordering operator<=>(const error_condition& lhs, const error_condition& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns \begin{codeblock} -lhs.category() < rhs.category() || -(lhs.category() == rhs.category() && lhs.value() < rhs.value()) +if (auto c = lhs.category() <=> rhs.category(); c != 0) return c; +return lhs.value() <=> rhs.value(); \end{codeblock} \end{itemdescr} diff --git a/source/iostreams.tex b/source/iostreams.tex index 543b601772..31e5c81b06 100644 --- a/source/iostreams.tex +++ b/source/iostreams.tex @@ -10848,6 +10848,8 @@ uintmax_t capacity; uintmax_t free; uintmax_t available; + + friend bool operator==(const space_info&, const space_info&) = default; }; // \ref{fs.enum}, enumerations @@ -11197,11 +11199,7 @@ // \ref{fs.path.nonmember}, non-member operators friend bool operator==(const path& lhs, const path& rhs) noexcept; - friend bool operator!=(const path& lhs, const path& rhs) noexcept; - friend bool operator< (const path& lhs, const path& rhs) noexcept; - friend bool operator<=(const path& lhs, const path& rhs) noexcept; - friend bool operator> (const path& lhs, const path& rhs) noexcept; - friend bool operator>=(const path& lhs, const path& rhs) noexcept; + friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept; friend path operator/ (const path& lhs, const path& rhs); @@ -12793,7 +12791,7 @@ \begin{itemdescr} \pnum -\returns \tcode{!(lhs < rhs) \&\& !(rhs < lhs)}. +\returns \tcode{lhs.compare(rhs) == 0}. \indextext{path equality} \pnum @@ -12813,54 +12811,14 @@ file'', and choose the appropriate function accordingly. \end{note} \end{itemdescr} -\indexlibrarymember{operator"!=}{path}% -\begin{itemdecl} -friend bool operator!=(const path& lhs, const path& rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(lhs == rhs)}. -\end{itemdescr} - -\indexlibrarymember{operator<}{path}% -\begin{itemdecl} -friend bool operator< (const path& lhs, const path& rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{lhs.compare(rhs) < 0}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{path}% -\begin{itemdecl} -friend bool operator<=(const path& lhs, const path& rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(rhs < lhs)}. -\end{itemdescr} - -\indexlibrarymember{operator>}{path}% -\begin{itemdecl} -friend bool operator> (const path& lhs, const path& rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{rhs < lhs}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{path}% +\indexlibrarymember{operator<=>}{path}% \begin{itemdecl} -friend bool operator>=(const path& lhs, const path& rhs) noexcept; +friend strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{!(lhs < rhs)}. +\returns \tcode{lhs.compare(rhs) <=> 0}. \end{itemdescr} \indexlibrarymember{operator/}{path}% @@ -13254,6 +13212,9 @@ // \ref{fs.file.status.obs}, observers file_type type() const noexcept; perms permissions() const noexcept; + + friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept + { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); } }; } \end{codeblock} @@ -13379,11 +13340,7 @@ file_status symlink_status(error_code& ec) const noexcept; bool operator==(const directory_entry& rhs) const noexcept; - bool operator!=(const directory_entry& rhs) const noexcept; - bool operator< (const directory_entry& rhs) const noexcept; - bool operator> (const directory_entry& rhs) const noexcept; - bool operator<=(const directory_entry& rhs) const noexcept; - bool operator>=(const directory_entry& rhs) const noexcept; + strong_ordering operator<=>(const directory_entry& rhs) const noexcept; private: filesystem::path pathobject; // \expos @@ -13755,54 +13712,14 @@ \returns \tcode{pathobject == rhs.pathobject}. \end{itemdescr} -\indexlibrarymember{operator"!=}{directory_entry}% -\begin{itemdecl} -bool operator!=(const directory_entry& rhs) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{pathobject != rhs.pathobject}. -\end{itemdescr} - -\indexlibrarymember{operator<}{directory_entry}% -\begin{itemdecl} -bool operator< (const directory_entry& rhs) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{pathobject < rhs.pathobject}. -\end{itemdescr} - -\indexlibrarymember{operator>}{directory_entry}% -\begin{itemdecl} -bool operator> (const directory_entry& rhs) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{pathobject > rhs.pathobject}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{directory_entry}% -\begin{itemdecl} -bool operator<=(const directory_entry& rhs) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{pathobject <= rhs.pathobject}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{directory_entry}% +\indexlibrarymember{operator<=>}{directory_entry}% \begin{itemdecl} -bool operator>=(const directory_entry& rhs) const noexcept; +strong_ordering operator<=>(const directory_entry& rhs) const noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{pathobject >= rhs.pathobject}. +\returns \tcode{pathobject <=> rhs.pathobject}. \end{itemdescr} \rSec2[fs.class.directory.iterator]{Class \tcode{directory_iterator}} diff --git a/source/iterators.tex b/source/iterators.tex index 54a0a2e6eb..6cb29652b1 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -292,6 +292,10 @@ constexpr bool operator>=( const reverse_iterator& x, const reverse_iterator& y); + template Iterator2> + constexpr compare_three_way_result_t + operator<=>(const reverse_iterator& x, + const reverse_iterator& y); template constexpr auto operator-( @@ -331,9 +335,6 @@ template constexpr bool operator==( const move_iterator& x, const move_iterator& y); - template - constexpr bool operator!=( - const move_iterator& x, const move_iterator& y); template constexpr bool operator<( const move_iterator& x, const move_iterator& y); @@ -346,6 +347,10 @@ template constexpr bool operator>=( const move_iterator& x, const move_iterator& y); + template Iterator2> + constexpr compare_three_way_result_t + operator<=>(const move_iterator& x, + const move_iterator& y); template constexpr auto operator-( @@ -395,9 +400,6 @@ template bool operator==(const istream_iterator& x, const istream_iterator& y); - template - bool operator!=(const istream_iterator& x, - const istream_iterator& y); template> class ostream_iterator; @@ -407,9 +409,6 @@ template bool operator==(const istreambuf_iterator& a, const istreambuf_iterator& b); - template - bool operator!=(const istreambuf_iterator& a, - const istreambuf_iterator& b); template> class ostreambuf_iterator; @@ -3395,6 +3394,26 @@ \tcode{x.base() <= y.base()}. \end{itemdescr} +\indexlibrarymember{operator<=>}{reverse_iterator}% +\begin{itemdecl} +template Iterator2> + constexpr compare_three_way_result_t + operator<=>(const reverse_iterator& x, + const reverse_iterator& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{y.base() <=> x.base()}. + +\pnum +\begin{note} +The argument order in the \returns element is reversed +because this is a reverse iterator. +\end{note} +\end{itemdescr} + \rSec3[reverse.iter.nonmember]{Non-member functions} \indexlibrarymember{operator-}{reverse_iterator}% @@ -3944,15 +3963,6 @@ template S> friend constexpr bool operator==(const move_iterator& x, const move_sentinel& y); - template S> - friend constexpr bool - operator==(const move_sentinel& x, const move_iterator& y); - template S> - friend constexpr bool - operator!=(const move_iterator& x, const move_sentinel& y); - template S> - friend constexpr bool - operator!=(const move_sentinel& x, const move_iterator& y); template S> friend constexpr iter_difference_t operator-(const move_sentinel& x, const move_iterator& y); @@ -4208,9 +4218,6 @@ template S> friend constexpr bool operator==(const move_iterator& x, const move_sentinel& y); -template S> - friend constexpr bool operator==(const move_sentinel& x, - const move_iterator& y); \end{itemdecl} \begin{itemdescr} @@ -4223,29 +4230,6 @@ \returns \tcode{x.base() == y.base()}. \end{itemdescr} -\indexlibrarymember{operator"!=}{move_iterator}% -\begin{itemdecl} -template - constexpr bool operator!=(const move_iterator& x, - const move_iterator& y); -template S> - friend constexpr bool operator!=(const move_iterator& x, - const move_sentinel& y); -template S> - friend constexpr bool operator!=(const move_sentinel& x, - const move_iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\constraints -\tcode{x.base() == y.base()} is well-formed and -convertible to \tcode{bool}. - -\pnum -\returns \tcode{!(x == y)}. -\end{itemdescr} - \indexlibrarymember{operator<}{move_iterator}% \begin{itemdecl} template @@ -4310,6 +4294,20 @@ \returns \tcode{!(x < y)}. \end{itemdescr} +\indexlibrarymember{operator<=>}{move_iterator}% +\begin{itemdecl} +template Iterator2> + constexpr compare_three_way_result_t + operator<=>(const move_iterator& x, + const move_iterator& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.base() <=> y.base()}. +\end{itemdescr} + \rSec3[move.iter.nonmember]{Non-member functions} \indexlibrarymember{operator-}{move_iterator}% @@ -4545,10 +4543,6 @@ requires Sentinel && EqualityComparableWith friend bool operator==( const common_iterator& x, const common_iterator& y); - template S2> - requires Sentinel - friend bool operator!=( - const common_iterator& x, const common_iterator& y); template I2, SizedSentinel S2> requires SizedSentinel @@ -4828,19 +4822,6 @@ $i$ is \tcode{x.v_.index()} and $j$ is \tcode{y.v_.index()}. \end{itemdescr} -\indexlibrarymember{operator"!=}{common_iterator}% -\begin{itemdecl} -template S2> - requires Sentinel -friend bool operator!=( - const common_iterator& x, const common_iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - \indexlibrarymember{operator-}{common_iterator}% \begin{itemdecl} template I2, SizedSentinel S2> @@ -5006,28 +4987,9 @@ const counted_iterator& x, const counted_iterator& y); friend constexpr bool operator==( const counted_iterator& x, default_sentinel_t); - friend constexpr bool operator==( - default_sentinel_t, const counted_iterator& x); - - template I2> - friend constexpr bool operator!=( - const counted_iterator& x, const counted_iterator& y); - friend constexpr bool operator!=( - const counted_iterator& x, default_sentinel_t y); - friend constexpr bool operator!=( - default_sentinel_t x, const counted_iterator& y); template I2> - friend constexpr bool operator<( - const counted_iterator& x, const counted_iterator& y); - template I2> - friend constexpr bool operator>( - const counted_iterator& x, const counted_iterator& y); - template I2> - friend constexpr bool operator<=( - const counted_iterator& x, const counted_iterator& y); - template I2> - friend constexpr bool operator>=( + friend constexpr strong_ordering operator<=>( const counted_iterator& x, const counted_iterator& y); friend constexpr iter_rvalue_reference_t iter_move(const counted_iterator& i) @@ -5373,8 +5335,6 @@ \begin{itemdecl} friend constexpr bool operator==( const counted_iterator& x, default_sentinel_t); -friend constexpr bool operator==( - default_sentinel_t, const counted_iterator& x); \end{itemdecl} \begin{itemdescr} @@ -5382,26 +5342,10 @@ \effects Equivalent to: \tcode{return x.length == 0;} \end{itemdescr} -\indexlibrarymember{operator"!=}{counted_iterator}% +\indexlibrarymember{operator<=>}{counted_iterator}% \begin{itemdecl} template I2> - friend constexpr bool operator!=( - const counted_iterator& x, const counted_iterator& y); -friend constexpr bool operator!=( - const counted_iterator& x, default_sentinel_t y); -friend constexpr bool operator!=( - default_sentinel_t x, const counted_iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - -\indexlibrarymember{operator<}{counted_iterator}% -\begin{itemdecl} -template I2> - friend constexpr bool operator<( + friend constexpr strong_ordering operator<=>( const counted_iterator& x, const counted_iterator& y); \end{itemdecl} @@ -5412,51 +5356,16 @@ elements of the same sequence\iref{counted.iterator}. \pnum -\effects Equivalent to: \tcode{return y.length < x.length;} +\effects +Equivalent to: \tcode{return y.length <=> x.length;} \pnum \begin{note} -The argument order in the \effects{} element is reversed +The argument order in the \effects element is reversed because \tcode{length} counts down, not up. \end{note} \end{itemdescr} -\indexlibrarymember{operator>}{counted_iterator}% -\begin{itemdecl} -template I2> - friend constexpr bool operator>( - const counted_iterator& x, const counted_iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return y < x;} -\end{itemdescr} - -\indexlibrarymember{operator<=}{counted_iterator}% -\begin{itemdecl} -template I2> - friend constexpr bool operator<=( - const counted_iterator& x, const counted_iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(y < x);} -\end{itemdescr} - -\indexlibrarymember{operator>=}{counted_iterator}% -\begin{itemdecl} -template I2> - friend constexpr bool operator>=( - const counted_iterator& x, const counted_iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x < y);} -\end{itemdescr} - \rSec3[counted.iter.cust]{Customizations} \indexlibrarymember{iter_move}{counted_iterator}% @@ -5509,51 +5418,17 @@ conditional branch. \end{example} +\indexlibrarymember{operator==}{unreachable_sentinel_t}% \begin{codeblock} namespace std { struct unreachable_sentinel_t { template - friend constexpr bool operator==(unreachable_sentinel_t, const I&) noexcept; - template - friend constexpr bool operator==(const I&, unreachable_sentinel_t) noexcept; - template - friend constexpr bool operator!=(unreachable_sentinel_t, const I&) noexcept; - template - friend constexpr bool operator!=(const I&, unreachable_sentinel_t) noexcept; + friend constexpr bool operator==(unreachable_sentinel_t, const I&) noexcept + { return false; } }; } \end{codeblock} -\rSec3[unreachable.sentinel.cmp]{Comparisons} - -\indexlibrary{\idxcode{operator==}!\idxcode{unreachable_sentinel_t}}% -\indexlibrary{\idxcode{unreachable_sentinel_t}!\idxcode{operator==}}% -\begin{itemdecl} -template - friend constexpr bool operator==(unreachable_sentinel_t, const I&) noexcept; -template - friend constexpr bool operator==(const I&, unreachable_sentinel_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{false}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{unreachable_sentinel_t}}% -\indexlibrary{\idxcode{unreachable_sentinel_t}!\idxcode{operator"!=}}% -\begin{itemdecl} -template - friend constexpr bool operator!=(unreachable_sentinel_t, const I&) noexcept; -template - friend constexpr bool operator!=(const I&, unreachable_sentinel_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{true}. -\end{itemdescr} - \rSec1[stream.iterators]{Stream iterators} \pnum @@ -5611,9 +5486,6 @@ istream_iterator operator++(int); friend bool operator==(const istream_iterator& i, default_sentinel_t); - friend bool operator==(default_sentinel_t, const istream_iterator& i); - friend bool operator!=(const istream_iterator& x, default_sentinel_t y); - friend bool operator!=(default_sentinel_t x, const istream_iterator& y); private: basic_istream* in_stream; // \expos @@ -5778,7 +5650,6 @@ \indexlibrarymember{operator==}{istream_iterator}% \begin{itemdecl} -friend bool operator==(default_sentinel_t, const istream_iterator& i); friend bool operator==(const istream_iterator& i, default_sentinel_t); \end{itemdecl} @@ -5788,21 +5659,6 @@ \tcode{!i.in_stream}. \end{itemdescr} -\indexlibrarymember{operator"!=}{istream_iterator}% -\begin{itemdecl} -template - bool operator!=(const istream_iterator& x, - const istream_iterator& y); -friend bool operator!=(default_sentinel_t x, const istream_iterator& y); -friend bool operator!=(const istream_iterator& x, default_sentinel_t y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!(x == y)} -\end{itemdescr} - \rSec2[ostream.iterator]{Class template \tcode{ostream_iterator}} \pnum @@ -5992,10 +5848,7 @@ @\placeholder{proxy}@ operator++(int); bool equal(const istreambuf_iterator& b) const; - friend bool operator==(default_sentinel_t s, const istreambuf_iterator& i); friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s); - friend bool operator!=(default_sentinel_t a, const istreambuf_iterator& b); - friend bool operator!=(const istreambuf_iterator& a, default_sentinel_t b); private: streambuf_type* sbuf_; // \expos @@ -6162,7 +6015,6 @@ \indexlibrarymember{operator==}{istreambuf_iterator}% \begin{itemdecl} -friend bool operator==(default_sentinel_t s, const istreambuf_iterator& i); friend bool operator==(const istreambuf_iterator& i, default_sentinel_t s); \end{itemdecl} @@ -6171,21 +6023,6 @@ \returns \tcode{i.equal(s)}. \end{itemdescr} -\indexlibrarymember{operator"!=}{istreambuf_iterator}% -\begin{itemdecl} -template - bool operator!=(const istreambuf_iterator& a, - const istreambuf_iterator& b); -friend bool operator!=(default_sentinel_t a, const istreambuf_iterator& b); -friend bool operator!=(const istreambuf_iterator& a, default_sentinel_t b); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!a.equal(b)}. -\end{itemdescr} - \rSec2[ostreambuf.iterator]{Class template \tcode{ostreambuf_iterator}} \pnum diff --git a/source/lib-intro.tex b/source/lib-intro.tex index f36e1c91f1..f06eb7acb1 100644 --- a/source/lib-intro.tex +++ b/source/lib-intro.tex @@ -707,13 +707,32 @@ The declaration of such a function is followed by a comment ending in \expos. \pnum -The following function is defined for exposition only +The following are defined for exposition only to aid in the specification of the library: \indexlibrary{decay-copy@\tcode{\placeholder{decay-copy}}}% \begin{codeblock} template constexpr decay_t @\placeholdernc{decay-copy}@(T&& v) noexcept(is_nothrow_convertible_v>) // \expos { return std::forward(v); } + +constexpr auto @\placeholdernc{synth-three-way}@ = + [](const T& t, const U& u) + requires requires { + { t < u } -> ConvertibleTo; + { u < t } -> ConvertibleTo; + } + { + if constexpr (ThreeWayComparableWith) { + return t <=> u; + } else { + if (t < u) return weak_ordering::less; + if (u < t) return weak_ordering::greater; + return weak_ordering::equivalent; + } + }; + +template +using @\placeholdernc{synth-three-way-result}@ = decltype(@\placeholdernc{synth-three-way}@(declval(), declval())); \end{codeblock} \rSec3[type.descriptions]{Type descriptions} @@ -1040,75 +1059,6 @@ the implementation provides explicit definitions for such member function signatures, or for virtual destructors that can be generated by default. -\rSec3[operators]{Operators} - -\pnum -In this library, whenever a declaration is provided for an \tcode{operator!=}, -\tcode{operator>}, \tcode{operator<=}, or \tcode{operator>=} -for a type \tcode{T}, -its requirements and semantics are as follows, -unless explicitly specified otherwise. - -\indexlibrary{\idxcode{operator"!=}}% -\begin{itemdecl} -bool operator!=(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\requires -Type \tcode{T} is \oldconcept{EqualityComparable} (\tref{cpp17.equalitycomparable}). - -\pnum -\returns -\tcode{!(x == y)}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator>}}% -\begin{itemdecl} -bool operator>(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\requires -Type \tcode{T} is \oldconcept{LessThanComparable} (\tref{cpp17.lessthancomparable}). - -\pnum -\returns -\tcode{y < x}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator<=}}% -\begin{itemdecl} -bool operator<=(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\requires -Type \tcode{T} is \oldconcept{LessThanComparable} (\tref{cpp17.lessthancomparable}). - -\pnum -\returns -\tcode{!(y < x)}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator>=}}% -\begin{itemdecl} -bool operator>=(const T& x, const T& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\requires -Type \tcode{T} is \oldconcept{LessThanComparable} (\tref{cpp17.lessthancomparable}). - -\pnum -\returns -\tcode{!(x < y)}. -\end{itemdescr} - \rSec3[objects.within.classes]{Private members} \pnum diff --git a/source/locales.tex b/source/locales.tex index be18eb747b..11a2836e83 100644 --- a/source/locales.tex +++ b/source/locales.tex @@ -147,7 +147,6 @@ basic_string name() const; bool operator==(const locale& other) const; - bool operator!=(const locale& other) const; template bool operator()(const basic_string& s1, @@ -808,16 +807,6 @@ otherwise. \end{itemdescr} -\indexlibrarymember{locale}{operator"!=}% -\begin{itemdecl} -bool operator!=(const locale& other) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(*this == other)}. -\end{itemdescr} - \indexlibrarymember{locale}{operator()}% \begin{itemdecl} template diff --git a/source/numerics.tex b/source/numerics.tex index 9d580ac343..06423d91e3 100644 --- a/source/numerics.tex +++ b/source/numerics.tex @@ -248,11 +248,6 @@ template constexpr bool operator==(const complex&, const complex&); template constexpr bool operator==(const complex&, const T&); - template constexpr bool operator==(const T&, const complex&); - - template constexpr bool operator!=(const complex&, const complex&); - template constexpr bool operator!=(const complex&, const T&); - template constexpr bool operator!=(const T&, const complex&); template basic_istream& operator>>(basic_istream&, complex&); @@ -740,7 +735,6 @@ \begin{itemdecl} template constexpr bool operator==(const complex& lhs, const complex& rhs); template constexpr bool operator==(const complex& lhs, const T& rhs); -template constexpr bool operator==(const T& lhs, const complex& rhs); \end{itemdecl} \begin{itemdescr} @@ -757,19 +751,6 @@ arguments. \end{itemdescr} -\indexlibrarymember{operator"!=}{complex}% -\begin{itemdecl} -template constexpr bool operator!=(const complex& lhs, const complex& rhs); -template constexpr bool operator!=(const complex& lhs, const T& rhs); -template constexpr bool operator!=(const T& lhs, const complex& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{rhs.real() != lhs.real() || rhs.imag() != lhs.imag()}. -\end{itemdescr} - \indexlibrarymember{operator>>}{complex}% \begin{itemdecl} template @@ -7927,6 +7908,8 @@ size_t start() const; size_t size() const; size_t stride() const; + + friend bool operator==(const slice& x, const slice& y); }; } \end{codeblock} @@ -7988,6 +7971,22 @@ \complexity Constant time. \end{itemdescr} +\rSec3[slice.ops]{Operators} + +\indexlibrarymember{stride}{slice}% +\begin{itemdecl} +friend bool operator==(const slice& x, const slice& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return x.start() == y.start() && x.size() == y.size() && x.stride() == y.stride(); +\end{codeblock} +\end{itemdescr} + \rSec2[template.slice.array]{Class template \tcode{slice_array}} \rSec3[template.slice.array.overview]{Overview} diff --git a/source/ranges.tex b/source/ranges.tex index be8cd2b485..b65323b009 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -1910,8 +1910,6 @@ friend constexpr bool operator==(const iterator& x, const iterator& y) requires EqualityComparable; - friend constexpr bool operator!=(const iterator& x, const iterator& y) - requires EqualityComparable; friend constexpr bool operator<(const iterator& x, const iterator& y) requires StrictTotallyOrdered; @@ -1921,6 +1919,9 @@ requires StrictTotallyOrdered; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires StrictTotallyOrdered; + friend constexpr compare_three_way_result_t operator<=>( + const iterator& x, const iterator& y) + requires StrictTotallyOrdered && ThreeWayComparable; friend constexpr iterator operator+(iterator i, difference_type n) requires @\placeholdernc{Advanceable}@; @@ -2098,17 +2099,6 @@ \effects Equivalent to: \tcode{return x.value_ == y.value_;} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{iota_view::iterator}} -\begin{itemdecl} -friend constexpr bool operator!=(const iterator& x, const iterator& y) - requires EqualityComparable; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - \indexlibrary{\idxcode{operator<}!\idxcode{iota_view::iterator}} \begin{itemdecl} friend constexpr bool operator<(const iterator& x, const iterator& y) @@ -2153,6 +2143,19 @@ \effects Equivalent to: \tcode{return !(x < y);} \end{itemdescr} +\indexlibrary{\idxcode{operator<=>}!\idxcode{iota_view::iterator}} +\begin{itemdecl} +friend constexpr compare_three_way_result_t + operator<=>(const iterator& x, const iterator& y) + requires StrictTotallyOrdered && ThreeWayComparable; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.value_ <=> y.value_;} +\end{itemdescr} + \indexlibrary{\idxcode{operator+}!\idxcode{iota_view::iterator}} \begin{itemdecl} friend constexpr iterator operator+(iterator i, difference_type n) @@ -2210,9 +2213,6 @@ constexpr explicit sentinel(Bound bound); friend constexpr bool operator==(const iterator& x, const sentinel& y); - friend constexpr bool operator==(const sentinel& x, const iterator& y); - friend constexpr bool operator!=(const iterator& x, const sentinel& y); - friend constexpr bool operator!=(const sentinel& x, const iterator& y); }; } \end{codeblock} @@ -2237,36 +2237,6 @@ \effects Equivalent to: \tcode{return x.value_ == y.bound_;} \end{itemdescr} -\indexlibrary{\idxcode{operator==}!\idxcode{iota_view::sentinel}} -\begin{itemdecl} -friend constexpr bool operator==(const sentinel& x, const iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return y == x;} -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{iota_view::sentinel}} -\begin{itemdecl} -friend constexpr bool operator!=(const iterator& x, const sentinel& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{iota_view::sentinel}} -\begin{itemdecl} -friend constexpr bool operator!=(const sentinel& x, const iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(y == x);} -\end{itemdescr} - \rSec3[range.iota.adaptor]{\tcode{view::iota}} \pnum @@ -2633,8 +2603,6 @@ friend constexpr bool operator==(const iterator& x, const iterator& y) requires EqualityComparable>; - friend constexpr bool operator!=(const iterator& x, const iterator& y) - requires EqualityComparable>; friend constexpr iter_rvalue_reference_t> iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.current_))); @@ -2801,17 +2769,6 @@ \effects Equivalent to: \tcode{return x.current_ == y.current_;} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{filter_view::iterator}}% -\begin{itemdecl} -friend constexpr bool operator!=(const iterator& x, const iterator& y) - requires EqualityComparable>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - \indexlibrary{\idxcode{iter_move}!\idxcode{filter_view::iterator}}% \begin{itemdecl} friend constexpr iter_rvalue_reference_t> iter_move(const iterator& i) @@ -2851,9 +2808,6 @@ constexpr sentinel_t base() const; friend constexpr bool operator==(const iterator& x, const sentinel& y); - friend constexpr bool operator==(const sentinel& x, const iterator& y); - friend constexpr bool operator!=(const iterator& x, const sentinel& y); - friend constexpr bool operator!=(const sentinel& x, const iterator& y); }; } \end{codeblock} @@ -2888,36 +2842,6 @@ \effects Equivalent to: \tcode{return x.current_ == y.end_;} \end{itemdescr} -\indexlibrary{\idxcode{operator==}!\idxcode{filter_view::sentinel}}% -\begin{itemdecl} -friend constexpr bool operator==(const sentinel& x, const iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return y == x;} -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{filter_view::sentinel}}% -\begin{itemdecl} -friend constexpr bool operator!=(const iterator& x, const sentinel& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{filter_view::sentinel}}% -\begin{itemdecl} -friend constexpr bool operator!=(const sentinel& x, const iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(y == x);} -\end{itemdescr} - \rSec3[range.filter.adaptor]{\tcode{view::filter}} \pnum @@ -3163,8 +3087,6 @@ friend constexpr bool operator==(const iterator& x, const iterator& y) requires EqualityComparable>; - friend constexpr bool operator!=(const iterator& x, const iterator& y) - requires EqualityComparable>; friend constexpr bool operator<(const iterator& x, const iterator& y) requires RandomAccessRange; @@ -3174,6 +3096,9 @@ requires RandomAccessRange; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires RandomAccessRange; + friend constexpr compare_three_way_result_t> + operator<=>(const iterator& x, const iterator& y) + requires RandomAccessRange && ThreeWayComparable>; friend constexpr iterator operator+(iterator i, difference_type n) requires RandomAccessRange; @@ -3366,17 +3291,6 @@ \effects Equivalent to: \tcode{return x.current_ == y.current_;} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{transform_view::iterator}}% -\begin{itemdecl} -friend constexpr bool operator!=(const iterator& x, const iterator& y) - requires EqualityComparable>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - \indexlibrary{\idxcode{operator<}!\idxcode{transform_view::iterator}}% \begin{itemdecl} friend constexpr bool operator<(const iterator& x, const iterator& y) @@ -3421,6 +3335,18 @@ \effects Equivalent to: \tcode{return !(x < y);} \end{itemdescr} +\indexlibrary{\idxcode{operator<=>}!\idxcode{transform_view::iterator}}% +\begin{itemdecl} +friend constexpr compare_three_way_result_t> + operator<=>(const iterator& x, const iterator& y) + requires RandomAccessRange && ThreeWayComparable>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects Equivalent to: \tcode{return x.current_ <=> y.current_;} +\end{itemdescr} + \indexlibrary{\idxcode{operator+}!\idxcode{transform_view::iterator}} \begin{itemdecl} friend constexpr iterator operator+(iterator i, difference_type n) @@ -3490,9 +3416,6 @@ constexpr sentinel_t base() const; friend constexpr bool operator==(const iterator& x, const sentinel& y); - friend constexpr bool operator==(const sentinel& x, const iterator& y); - friend constexpr bool operator!=(const iterator& x, const sentinel& y); - friend constexpr bool operator!=(const sentinel& x, const iterator& y); friend constexpr iter_difference_t> operator-(const iterator& x, const sentinel& y) @@ -3545,60 +3468,6 @@ \effects Equivalent to: \tcode{return x.current_ == y.end_;} \end{itemdescr} -\indexlibrary{\idxcode{operator==}!\idxcode{transform_view::sentinel}} -\begin{itemdecl} -friend constexpr bool operator==(const sentinel& x, const iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return y == x;} -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{transform_view::sentinel}}% -\begin{itemdecl} -friend constexpr bool operator!=(const iterator& x, const sentinel& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{transform_view::sentinel}}% -\begin{itemdecl} -friend constexpr bool operator!=(const sentinel& x, const iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(y == x);} -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{transform_view::sentinel}}% -\begin{itemdecl} -friend constexpr iter_difference_t> - operator-(const iterator& x, const sentinel& y) - requires SizedSentinel, iterator_t>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return x.current_ - y.end_;} -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{transform_view::sentinel}}% -\begin{itemdecl} -friend constexpr iter_difference_t> - operator-(const sentinel& y, const iterator& x) - requires SizedSentinel, iterator_t>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return x.end_ - y.current_;} -\end{itemdescr} - \rSec3[range.transform.adaptor]{\tcode{view::transform}} \pnum @@ -3758,10 +3627,7 @@ constexpr sentinel_t base() const; - friend constexpr bool operator==(const sentinel& x, const CI& y); friend constexpr bool operator==(const CI& y, const sentinel& x); - friend constexpr bool operator!=(const sentinel& x, const CI& y); - friend constexpr bool operator!=(const CI& y, const sentinel& x); }; } \end{codeblock} @@ -3799,7 +3665,6 @@ \indexlibrary{\idxcode{operator==}!\idxcode{take_view::sentinel}} \begin{itemdecl} -friend constexpr bool operator==(const sentinel& x, const CI& y); friend constexpr bool operator==(const CI& y, const sentinel& x); \end{itemdecl} @@ -3809,17 +3674,6 @@ \tcode{return y.count() == 0 || y.base() == x.end_;} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{take_view::sentinel}}% -\begin{itemdecl} -friend constexpr bool operator!=(const sentinel& x, const CI& y); -friend constexpr bool operator!=(const CI& y, const sentinel& x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - \rSec3[range.take.adaptor]{\tcode{view::take}} \pnum @@ -3998,10 +3852,6 @@ requires ref_is_glvalue && EqualityComparable> && EqualityComparable>>>; - friend constexpr bool operator!=(const iterator& x, const iterator& y) - requires ref_is_glvalue && EqualityComparable> && - EqualityComparable>>>; - friend constexpr decltype(auto) iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.inner_))) { return ranges::iter_move(i.inner_); @@ -4225,18 +4075,6 @@ \tcode{return x.outer_ == y.outer_ \&\& x.inner_ == y.inner_;} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{join_view::iterator}} -\begin{itemdecl} -friend constexpr bool operator!=(const iterator& x, const iterator& y) - requires ref_is_glvalue && EqualityComparable> && - EqualityComparable>>>; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - \indexlibrary{\idxcode{iter_swap}!\idxcode{join_view::iterator}} \begin{itemdecl} friend constexpr void iter_swap(const iterator& x, const iterator& y) @@ -4268,9 +4106,6 @@ requires Const && ConvertibleTo, sentinel_t>; friend constexpr bool operator==(const iterator& x, const sentinel& y); - friend constexpr bool operator==(const sentinel& x, const iterator& y); - friend constexpr bool operator!=(const iterator& x, const sentinel& y); - friend constexpr bool operator!=(const sentinel& x, const iterator& y); }; } \end{codeblock} @@ -4306,36 +4141,6 @@ \effects Equivalent to: \tcode{return x.outer_ == y.end_;} \end{itemdescr} -\indexlibrary{\idxcode{operator==}!\idxcode{join_view::sentinel}} -\begin{itemdecl} -friend constexpr bool operator==(const sentinel& x, const iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return y == x;} -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{join_view::sentinel}} -\begin{itemdecl} -friend constexpr bool operator!=(const iterator& x, const sentinel& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - -\indexlibrary{\idxcode{operator"!=}!\idxcode{join_view::sentinel}} -\begin{itemdecl} -friend constexpr bool operator!=(const sentinel& x, const iterator& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(y == x);} -\end{itemdescr} - \rSec3[range.join.adaptor]{\tcode{view::join}} \pnum @@ -4528,13 +4333,8 @@ friend constexpr bool operator==(const outer_iterator& x, const outer_iterator& y) requires ForwardRange; - friend constexpr bool operator!=(const outer_iterator& x, const outer_iterator& y) - requires ForwardRange; friend constexpr bool operator==(const outer_iterator& x, default_sentinel_t); - friend constexpr bool operator==(default_sentinel_t, const outer_iterator& x); - friend constexpr bool operator!=(const outer_iterator& x, default_sentinel_t y); - friend constexpr bool operator!=(default_sentinel_t y, const outer_iterator& x); }; } \end{codeblock} @@ -4627,21 +4427,9 @@ \effects Equivalent to: \tcode{return x.current_ == y.current_;} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{split_view::outer_iterator}}% -\begin{itemdecl} -friend constexpr bool operator!=(const outer_iterator& x, const outer_iterator& y) - requires ForwardRange; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - \indexlibrary{\idxcode{operator==}!\idxcode{split_view::outer_iterator}}% \begin{itemdecl} friend constexpr bool operator==(const outer_iterator& x, default_sentinel_t); -friend constexpr bool operator==(default_sentinel_t, const outer_iterator& x); \end{itemdecl} \begin{itemdescr} @@ -4650,17 +4438,6 @@ Equivalent to: \tcode{return x.\placeholder{current} == ranges::end(x.parent_->base_);} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{split_view::outer_iterator}}% -\begin{itemdecl} -friend constexpr bool operator!=(const outer_iterator& x, default_sentinel_t y); -friend constexpr bool operator!=(default_sentinel_t y, const outer_iterator& x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - \rSec3[range.split.outer.value]{Class \tcode{split_view::outer_iterator::value_type}} \begin{codeblock} @@ -4745,13 +4522,8 @@ friend constexpr bool operator==(const inner_iterator& x, const inner_iterator& y) requires ForwardRange; - friend constexpr bool operator!=(const inner_iterator& x, const inner_iterator& y) - requires ForwardRange; friend constexpr bool operator==(const inner_iterator& x, default_sentinel_t); - friend constexpr bool operator==(default_sentinel_t, const inner_iterator& x); - friend constexpr bool operator!=(const inner_iterator& x, default_sentinel_t y); - friend constexpr bool operator!=(default_sentinel_t y, const inner_iterator& x); friend constexpr decltype(auto) iter_move(const inner_iterator& i) noexcept(noexcept(ranges::iter_move(i.i_.@\placeholdernc{current}@))) { @@ -4813,21 +4585,9 @@ \effects Equivalent to: \tcode{return x.i_.current_ == y.i_.current_;} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{split_view::inner_iterator}}% -\begin{itemdecl} -friend constexpr bool operator!=(const inner_iterator& x, const inner_iterator& y) - requires ForwardRange; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - \indexlibrary{\idxcode{operator==}!\idxcode{split_view::inner_iterator}}% \begin{itemdecl} friend constexpr bool operator==(const inner_iterator& x, default_sentinel_t); -friend constexpr bool operator==(default_sentinel_t, const inner_iterator& x); \end{itemdecl} \begin{itemdescr} @@ -4847,17 +4607,6 @@ \end{codeblock} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{split_view::inner_iterator}}% -\begin{itemdecl} -friend constexpr bool operator!=(const inner_iterator& x, default_sentinel_t y); -friend constexpr bool operator!=(default_sentinel_t y, const inner_iterator& x); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\effects Equivalent to: \tcode{return !(x == y);} -\end{itemdescr} - \indexlibrary{\idxcode{iter_swap}!\idxcode{split_view::inner_iterator}}% \begin{itemdecl} friend constexpr void iter_swap(const inner_iterator& x, const inner_iterator& y) diff --git a/source/regex.tex b/source/regex.tex index 72c3b73cce..cd50eac125 100644 --- a/source/regex.tex +++ b/source/regex.tex @@ -298,141 +298,30 @@ template bool operator==(const sub_match& lhs, const sub_match& rhs); template - bool operator!=(const sub_match& lhs, const sub_match& rhs); - template - bool operator<(const sub_match& lhs, const sub_match& rhs); - template - bool operator>(const sub_match& lhs, const sub_match& rhs); - template - bool operator<=(const sub_match& lhs, const sub_match& rhs); - template - bool operator>=(const sub_match& lhs, const sub_match& rhs); - - template - bool operator==( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); - template - bool operator!=( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); - template - bool operator<( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); - template - bool operator>( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); - template - bool operator<=( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); - template - bool operator>=( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); + constexpr auto operator<=>(const sub_match& lhs, const sub_match& rhs); template bool operator==( const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); template - bool operator!=( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); - template - bool operator<( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); - template - bool operator>( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); - template - bool operator<=( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); - template - bool operator>=( + auto operator<=>( const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); - template - bool operator==(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); - template - bool operator!=(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); - template - bool operator<(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); - template - bool operator>(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); - template - bool operator<=(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); - template - bool operator>=(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); - template bool operator==(const sub_match& lhs, const typename iterator_traits::value_type* rhs); template - bool operator!=(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); - template - bool operator<(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); - template - bool operator>(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); - template - bool operator<=(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); - template - bool operator>=(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); - - template - bool operator==(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); - template - bool operator!=(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); - template - bool operator<(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); - template - bool operator>(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); - template - bool operator<=(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); - template - bool operator>=(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); + auto operator<=>(const sub_match& lhs, + const typename iterator_traits::value_type* rhs); template bool operator==(const sub_match& lhs, const typename iterator_traits::value_type& rhs); template - bool operator!=(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); - template - bool operator<(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); - template - bool operator>(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); - template - bool operator<=(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); - template - bool operator>=(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); + auto operator<=>(const sub_match& lhs, + const typename iterator_traits::value_type& rhs); template basic_ostream& @@ -452,9 +341,6 @@ template bool operator==(const match_results& m1, const match_results& m2); - template - bool operator!=(const match_results& m1, - const match_results& m2); // \ref{re.results.swap}, \tcode{match_results} swap template @@ -1903,6 +1789,12 @@ \rSec2[re.submatch.op]{Non-member operators} +\pnum +Let \tcode{\placeholdernc{SM-CAT}(I)} be +\begin{codeblock} +compare_three_way_result_t::value_type>> +\end{codeblock} + \indexlibrarymember{sub_match}{operator==}% \begin{itemdecl} template @@ -1913,134 +1805,14 @@ \pnum\returns \tcode{lhs.compare(rhs) == 0}. \end{itemdescr} -\indexlibrarymember{sub_match}{operator"!=}% -\begin{itemdecl} -template - bool operator!=(const sub_match& lhs, const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{lhs.compare(rhs) != 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<}% +\indexlibrarymember{sub_match}{operator<=>}% \begin{itemdecl} template - bool operator<(const sub_match& lhs, const sub_match& rhs); + bool operator<=>(const sub_match& lhs, const sub_match& rhs); \end{itemdecl} \begin{itemdescr} -\pnum\returns \tcode{lhs.compare(rhs) < 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>}% -\begin{itemdecl} -template - bool operator>(const sub_match& lhs, const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{lhs.compare(rhs) > 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<=}% -\begin{itemdecl} -template - bool operator<=(const sub_match& lhs, const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{lhs.compare(rhs) <= 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>=}% -\begin{itemdecl} -template - bool operator>=(const sub_match& lhs, const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{lhs.compare(rhs) >= 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator==}% -\begin{itemdecl} -template - bool operator==( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\begin{codeblock} -rhs.compare(typename sub_match::string_type(lhs.data(), lhs.size())) == 0 -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator"!=}% -\begin{itemdecl} -template - bool operator!=( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(lhs == rhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<}% -\begin{itemdecl} -template - bool operator<( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\begin{codeblock} -rhs.compare(typename sub_match::string_type(lhs.data(), lhs.size())) > 0 -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>}% -\begin{itemdecl} -template - bool operator>( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{rhs < lhs}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<=}% -\begin{itemdecl} -template - bool operator<=( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(rhs < lhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>=}% -\begin{itemdecl} -template - bool operator>=( - const basic_string::value_type, ST, SA>& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(lhs < rhs)}. +\pnum\returns \tcode{static_cast<\placeholdernc{SM-CAT}(BiIter)>(lhs.compare(rhs) <=> 0)}. \end{itemdescr} \indexlibrarymember{operator==}{sub_match}% @@ -2059,138 +1831,24 @@ \end{codeblock} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{sub_match}}% -\indexlibrary{\idxcode{sub_match}!\idxcode{operator"!=}}% +\indexlibrarymember{operator<=>}{sub_match}% \begin{itemdecl} template - bool operator!=( + auto operator<=>( const sub_match& lhs, const basic_string::value_type, ST, SA>& rhs); \end{itemdecl} \begin{itemdescr} -\pnum\returns \tcode{!(lhs == rhs)}. -\end{itemdescr} - -\indexlibrary{\idxcode{operator>}!\idxcode{sub_match}}% -\indexlibrary{\idxcode{sub_match}!\idxcode{operator<}}% -\begin{itemdecl} -template - bool operator<( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns +\pnum\returns \begin{codeblock} -lhs.compare(typename sub_match::string_type(rhs.data(), rhs.size())) < 0 +static_cast<@\placeholdernc{SM-CAT}@(BiIter)>(lhs.compare( + typename sub_match::string_type(rhs.data(), rhs.size())) + <=> 0 + ) \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator>}{sub_match}% -\begin{itemdecl} -template - bool operator>( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{rhs < lhs}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{sub_match}% -\begin{itemdecl} -template - bool operator<=( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(rhs < lhs)}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{sub_match}% -\begin{itemdecl} -template - bool operator>=( - const sub_match& lhs, - const basic_string::value_type, ST, SA>& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(lhs < rhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator==}% -\begin{itemdecl} -template - bool operator==(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{rhs.compare(lhs) == 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator"!=}% -\begin{itemdecl} -template - bool operator!=(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(lhs == rhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<}% -\begin{itemdecl} -template - bool operator<(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{rhs.compare(lhs) > 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>}% -\begin{itemdecl} -template - bool operator>(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{rhs < lhs}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<=}% -\begin{itemdecl} -template - bool operator<=(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(rhs < lhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>=}% -\begin{itemdecl} -template - bool operator>=(const typename iterator_traits::value_type* lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(lhs < rhs)}. -\end{itemdescr} - \indexlibrarymember{sub_match}{operator==}% \begin{itemdecl} template @@ -2202,132 +1860,16 @@ \pnum\returns \tcode{lhs.compare(rhs) == 0}. \end{itemdescr} -\indexlibrarymember{sub_match}{operator"!=}% -\begin{itemdecl} -template - bool operator!=(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(lhs == rhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<}% -\begin{itemdecl} -template - bool operator<(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{lhs.compare(rhs) < 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>}% -\begin{itemdecl} -template - bool operator>(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{rhs < lhs}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<=}% -\begin{itemdecl} -template - bool operator<=(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(rhs < lhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>=}% -\begin{itemdecl} -template - bool operator>=(const sub_match& lhs, - const typename iterator_traits::value_type* rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(lhs < rhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator==}% -\begin{itemdecl} -template - bool operator==(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{rhs.compare(typename sub_match::string_type(1, lhs)) == 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator"!=}% -\begin{itemdecl} -template - bool operator!=(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(lhs == rhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<}% -\begin{itemdecl} -template - bool operator<(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{rhs.compare(typename sub_match::string_type(1, lhs)) > 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>}% -\begin{itemdecl} -template - bool operator>(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{rhs < lhs}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<=}% -\begin{itemdecl} -template - bool operator<=(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(rhs < lhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>=}% +\indexlibrarymember{sub_match}{operator<=>}% \begin{itemdecl} template - bool operator>=(const typename iterator_traits::value_type& lhs, - const sub_match& rhs); + auto operator<=>(const sub_match& lhs, + const typename iterator_traits::value_type* rhs); \end{itemdecl} \begin{itemdescr} -\pnum -\returns \tcode{!(lhs < rhs)}. +\pnum\returns +\tcode{static_cast<\placeholdernc{SM-CAT}(BiIter)>(lhs.compare(rhs) <=> 0)}. \end{itemdescr} \indexlibrarymember{sub_match}{operator==}% @@ -2342,64 +1884,22 @@ \returns \tcode{lhs.compare(typename sub_match::string_type(1, rhs)) == 0}. \end{itemdescr} -\indexlibrarymember{sub_match}{operator"!=}% +\indexlibrarymember{sub_match}{operator<=>}% \begin{itemdecl} template - bool operator!=(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(lhs == rhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<}% -\begin{itemdecl} -template - bool operator<(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{lhs.compare(typename sub_match::string_type(1, rhs)) < 0}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>}% -\begin{itemdecl} -template - bool operator>(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{rhs < lhs}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator<=}% -\begin{itemdecl} -template - bool operator<=(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(rhs < lhs)}. -\end{itemdescr} - -\indexlibrarymember{sub_match}{operator>=}% -\begin{itemdecl} -template - bool operator>=(const sub_match& lhs, - const typename iterator_traits::value_type& rhs); + auto operator<=>(const sub_match& lhs, + const typename iterator_traits::value_type& rhs); \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{!(lhs < rhs)}. +\returns +\begin{codeblock} +static_cast<@\placeholdernc{SM-CAT}@(BiIter)>(lhs.compare( + typename sub_match::string_type(1, rhs)) + <=> 0 + ) +\end{codeblock} \end{itemdescr} \indexlibrary{\idxcode{basic_ostream}}% @@ -2944,19 +2444,6 @@ \begin{note} The algorithm \tcode{equal} is defined in \ref{algorithms}. \end{note} \end{itemdescr} -\indexlibrary{\idxcode{operator"!=}!\idxcode{match_results}}% -\indexlibrary{\idxcode{match_results}!\idxcode{operator"!=}}% -\begin{itemdecl} -template -bool operator!=(const match_results& m1, - const match_results& m2); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(m1 == m2)}. -\end{itemdescr} - \rSec1[re.alg]{Regular expression algorithms} \rSec2[re.except]{Exceptions} @@ -3494,7 +2981,6 @@ regex_iterator(const regex_iterator&); regex_iterator& operator=(const regex_iterator&); bool operator==(const regex_iterator&) const; - bool operator!=(const regex_iterator&) const; const value_type& operator*() const; const value_type* operator->() const; regex_iterator& operator++(); @@ -3567,15 +3053,6 @@ otherwise \tcode{false}. \end{itemdescr} -\indexlibrarymember{regex_iterator}{operator"!=}% -\begin{itemdecl} -bool operator!=(const regex_iterator& right) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(*this == right)}. -\end{itemdescr} - \rSec3[re.regiter.deref]{Indirection} \indexlibrarymember{regex_iterator}{operator*}% @@ -3791,7 +3268,6 @@ regex_token_iterator(const regex_token_iterator&); regex_token_iterator& operator=(const regex_token_iterator&); bool operator==(const regex_token_iterator&) const; - bool operator!=(const regex_token_iterator&) const; const value_type& operator*() const; const value_type* operator->() const; regex_token_iterator& operator++(); @@ -3904,15 +3380,6 @@ \tcode{N == right.N}, and \tcode{subs == right.subs}. Otherwise returns \tcode{false}. \end{itemdescr} -\indexlibrarymember{regex_token_iterator}{operator"!=}% -\begin{itemdecl} -bool operator!=(const regex_token_iterator& right) const; -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(*this == right)}. -\end{itemdescr} - \rSec3[re.tokiter.deref]{Indirection} \indexlibrarymember{regex_token_iterator}{operator*}% diff --git a/source/strings.tex b/source/strings.tex index cbba04ae5d..b4ebc3fbbc 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -267,6 +267,7 @@ using off_type = streamoff; using pos_type = streampos; using state_type = mbstate_t; + using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; @@ -321,6 +322,7 @@ using off_type = streamoff; using pos_type = u8streampos; using state_type = mbstate_t; + using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; @@ -362,6 +364,7 @@ using off_type = streamoff; using pos_type = u16streampos; using state_type = mbstate_t; + using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; @@ -407,6 +410,7 @@ using off_type = streamoff; using pos_type = u32streampos; using state_type = mbstate_t; + using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; @@ -452,6 +456,7 @@ using off_type = streamoff; using pos_type = wstreampos; using state_type = mbstate_t; + using comparison_category = strong_ordering; static constexpr void assign(char_type& c1, const char_type& c2) noexcept; static constexpr bool eq(char_type c1, char_type c2) noexcept; @@ -585,59 +590,16 @@ template bool operator==(const basic_string& lhs, const basic_string& rhs) noexcept; - template - bool operator==(const charT* lhs, - const basic_string& rhs); template bool operator==(const basic_string& lhs, const charT* rhs); - template - bool operator!=(const basic_string& lhs, - const basic_string& rhs) noexcept; - template - bool operator!=(const charT* lhs, - const basic_string& rhs); - template - bool operator!=(const basic_string& lhs, - const charT* rhs); template - bool operator< (const basic_string& lhs, - const basic_string& rhs) noexcept; - template - bool operator< (const basic_string& lhs, - const charT* rhs); - template - bool operator< (const charT* lhs, - const basic_string& rhs); - template - bool operator> (const basic_string& lhs, - const basic_string& rhs) noexcept; - template - bool operator> (const basic_string& lhs, - const charT* rhs); - template - bool operator> (const charT* lhs, - const basic_string& rhs); - - template - bool operator<=(const basic_string& lhs, - const basic_string& rhs) noexcept; - template - bool operator<=(const basic_string& lhs, - const charT* rhs); - template - bool operator<=(const charT* lhs, - const basic_string& rhs); - template - bool operator>=(const basic_string& lhs, - const basic_string& rhs) noexcept; - template - bool operator>=(const basic_string& lhs, - const charT* rhs); + @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const basic_string& rhs) noexcept; template - bool operator>=(const charT* lhs, - const basic_string& rhs); + @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const charT* rhs); // \ref{string.special}, swap template @@ -3327,57 +3289,22 @@ template bool operator==(const basic_string& lhs, const basic_string& rhs) noexcept; -template - bool operator==(const charT* lhs, const basic_string& rhs); template bool operator==(const basic_string& lhs, const charT* rhs); template - bool operator!=(const basic_string& lhs, - const basic_string& rhs) noexcept; -template - bool operator!=(const charT* lhs, const basic_string& rhs); -template - bool operator!=(const basic_string& lhs, const charT* rhs); - -template - bool operator< (const basic_string& lhs, - const basic_string& rhs) noexcept; -template - bool operator< (const charT* lhs, const basic_string& rhs); -template - bool operator< (const basic_string& lhs, const charT* rhs); - -template - bool operator> (const basic_string& lhs, - const basic_string& rhs) noexcept; -template - bool operator> (const charT* lhs, const basic_string& rhs); + @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const basic_string& rhs) noexcept; template - bool operator> (const basic_string& lhs, const charT* rhs); - -template - bool operator<=(const basic_string& lhs, - const basic_string& rhs) noexcept; -template - bool operator<=(const charT* lhs, const basic_string& rhs); -template - bool operator<=(const basic_string& lhs, const charT* rhs); - -template - bool operator>=(const basic_string& lhs, - const basic_string& rhs) noexcept; -template - bool operator>=(const charT* lhs, const basic_string& rhs); -template - bool operator>=(const basic_string& lhs, const charT* rhs); + @\seebelow@ operator<=>(const basic_string& lhs, + @\itcorr@ const charT* rhs); \end{itemdecl} \begin{itemdescr} \pnum \effects Let \tcode{\placeholder{op}} be the operator. Equivalent to: \begin{codeblock} - return basic_string_view(lhs) @\placeholder{op}@ basic_string_view(rhs); +return basic_string_view(lhs) @\placeholder{op}@ basic_string_view(rhs); \end{codeblock} \end{itemdescr} @@ -3889,20 +3816,9 @@ constexpr bool operator==(basic_string_view x, basic_string_view y) noexcept; template - constexpr bool operator!=(basic_string_view x, - basic_string_view y) noexcept; - template - constexpr bool operator< (basic_string_view x, - basic_string_view y) noexcept; - template - constexpr bool operator> (basic_string_view x, - basic_string_view y) noexcept; - template - constexpr bool operator<=(basic_string_view x, - basic_string_view y) noexcept; - template - constexpr bool operator>=(basic_string_view x, - basic_string_view y) noexcept; + constexpr @\seebelow@ operator<=>(basic_string_view x, + @\itcorr@ basic_string_view y) noexcept; + // see \ref{string.view.comparison}, sufficient additional overloads of comparison functions // \ref{string.view.io}, inserters and extractors @@ -4818,6 +4734,8 @@ \tcode{sv <= t} & \tcode{sv <= S(t)} \\ \tcode{t >= sv} & \tcode{S(t) >= sv} \\ \tcode{sv >= t} & \tcode{sv >= S(t)} \\ +\tcode{t <=> sv} & \tcode{S(t) <=> sv} \\ +\tcode{sv <=> t} & \tcode{sv <=> S(t)} \\ \end{libtab2} \begin{example} A sample conforming implementation for \tcode{operator==} would be: @@ -4832,11 +4750,6 @@ type_identity_t> rhs) noexcept { return lhs.compare(rhs) == 0; } -template - constexpr bool operator==(type_identity_t> lhs, - basic_string_view rhs) noexcept { - return lhs.compare(rhs) == 0; - } \end{codeblock} \end{example} @@ -4853,69 +4766,21 @@ \tcode{lhs.compare(rhs) == 0}. \end{itemdescr} -\indexlibrarymember{operator"!=}{basic_string_view}% +\indexlibrarymember{operator<=>}{basic_string_view}% \begin{itemdecl} template - constexpr bool operator!=(basic_string_view lhs, - basic_string_view rhs) noexcept; + constexpr @\seebelow@ operator<=>(basic_string_view lhs, + @\itcorr@ basic_string_view rhs) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -\tcode{lhs.compare(rhs) != 0}. -\end{itemdescr} - -\indexlibrarymember{operator<}{basic_string_view}% -\begin{itemdecl} -template - constexpr bool operator<(basic_string_view lhs, - basic_string_view rhs) noexcept; -\end{itemdecl} +Let \tcode{R} denote the type \tcode{traits::comparison_category} if it exists, +otherwise \tcode{R} is \tcode{weak_ordering}. -\begin{itemdescr} -\pnum -\returns -\tcode{lhs.compare(rhs) < 0}. -\end{itemdescr} - -\indexlibrarymember{operator>}{basic_string_view}% -\begin{itemdecl} -template - constexpr bool operator>(basic_string_view lhs, - basic_string_view rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{lhs.compare(rhs) > 0}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{basic_string_view}% -\begin{itemdecl} -template - constexpr bool operator<=(basic_string_view lhs, - basic_string_view rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{lhs.compare(rhs) <= 0}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{basic_string_view}% -\begin{itemdecl} -template - constexpr bool operator>=(basic_string_view lhs, - basic_string_view rhs) noexcept; -\end{itemdecl} - -\begin{itemdescr} \pnum \returns -\tcode{lhs.compare(rhs) >= 0}. +\tcode{static_cast(lhs.compare(rhs) <=> 0)}. \end{itemdescr} \rSec2[string.view.io]{Inserters and extractors} diff --git a/source/support.tex b/source/support.tex index 990672e39e..fecc0cfba4 100644 --- a/source/support.tex +++ b/source/support.tex @@ -700,6 +700,8 @@ \tcode{} \\ \rowsep \defnlibxname{cpp_lib_shared_timed_mutex} & \tcode{201402L} & \tcode{} \\ \rowsep +\defnlibxname{cpp_lib_spaceship} & \tcode{201907L} & + \tcode{} \\ \rowsep \defnlibxname{cpp_lib_string_udls} & \tcode{201304L} & \tcode{} \\ \rowsep \defnlibxname{cpp_lib_string_view} & \tcode{201606L} & @@ -3006,7 +3008,6 @@ public: virtual ~type_info(); bool operator==(const type_info& rhs) const noexcept; - bool operator!=(const type_info& rhs) const noexcept; bool before(const type_info& rhs) const noexcept; size_t hash_code() const noexcept; const char* name() const noexcept; @@ -3043,17 +3044,6 @@ if the two values describe the same type. \end{itemdescr} -\indexlibrarymember{operator"!=}{type_info}% -\begin{itemdecl} -bool operator!=(const type_info& rhs) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!(*this == rhs)}. -\end{itemdescr} - \indexlibrarymember{before}{type_info}% \begin{itemdecl} bool before(const type_info& rhs) const noexcept; @@ -3806,12 +3796,30 @@ template using common_comparison_category_t = typename common_comparison_category::type; + // \ref{cmp.concept}, concept \tcode{ThreeWayComparable} + template + concept ThreeWayComparable = @\seebelow@; + template + concept ThreeWayComparableWith = @\seebelow@; + + // \ref{cmp.result}, result of three-way comparison + template struct compare_three_way_result; + + template + using compare_three_way_result_t = typename compare_three_way_result::type; + + // \ref{cmp.object}, class \tcode{compare_three_way} + struct compare_three_way; + // \ref{cmp.alg}, comparison algorithms - template constexpr strong_ordering strong_order(const T& a, const T& b); - template constexpr weak_ordering weak_order(const T& a, const T& b); - template constexpr partial_ordering partial_order(const T& a, const T& b); - template constexpr strong_equality strong_equal(const T& a, const T& b); - template constexpr weak_equality weak_equal(const T& a, const T& b); + inline namespace @\unspec@ { + inline constexpr @\unspec@ strong_order = @\unspec@; + inline constexpr @\unspec@ weak_order = @\unspec@; + inline constexpr @\unspec@ partial_order = @\unspec@; + inline constexpr @\unspec@ compare_strong_order_fallback = @\unspec@; + inline constexpr @\unspec@ compare_weak_order_fallback = @\unspec@; + inline constexpr @\unspec@ compare_partial_order_fallback = @\unspec@; + } } \end{codeblock} @@ -3890,9 +3898,7 @@ // comparisons friend constexpr bool operator==(weak_equality v, @\unspec@) noexcept; - friend constexpr bool operator!=(weak_equality v, @\unspec@) noexcept; - friend constexpr bool operator==(@\unspec@, weak_equality v) noexcept; - friend constexpr bool operator!=(@\unspec@, weak_equality v) noexcept; + friend constexpr bool operator==(weak_equality v, weak_equality w) noexcept = default; friend constexpr weak_equality operator<=>(weak_equality v, @\unspec@) noexcept; friend constexpr weak_equality operator<=>(@\unspec@, weak_equality v) noexcept; }; @@ -3906,7 +3912,6 @@ \indexlibrarymember{operator==}{weak_equality}% \begin{itemdecl} constexpr bool operator==(weak_equality v, @\unspec@) noexcept; -constexpr bool operator==(@\unspec@, weak_equality v) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3915,18 +3920,6 @@ \tcode{v.value == 0}. \end{itemdescr} -\indexlibrarymember{operator"!=}{weak_equality}% -\begin{itemdecl} -constexpr bool operator!=(weak_equality v, @\unspec@) noexcept; -constexpr bool operator!=(@\unspec@, weak_equality v) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{v.value != 0}. -\end{itemdescr} - \indexlibrarymember{operator<=>}{weak_equality}% \begin{itemdecl} constexpr weak_equality operator<=>(weak_equality v, @\unspec@) noexcept; @@ -3972,9 +3965,7 @@ // comparisons friend constexpr bool operator==(strong_equality v, @\unspec@) noexcept; - friend constexpr bool operator!=(strong_equality v, @\unspec@) noexcept; - friend constexpr bool operator==(@\unspec@, strong_equality v) noexcept; - friend constexpr bool operator!=(@\unspec@, strong_equality v) noexcept; + friend constexpr bool operator==(strong_equality v, strong_equality w) noexcept = default; friend constexpr strong_equality operator<=>(strong_equality v, @\unspec@) noexcept; friend constexpr strong_equality operator<=>(@\unspec@, strong_equality v) noexcept; }; @@ -4001,7 +3992,6 @@ \indexlibrarymember{operator==}{strong_equality}% \begin{itemdecl} constexpr bool operator==(strong_equality v, @\unspec@) noexcept; -constexpr bool operator==(@\unspec@, strong_equality v) noexcept; \end{itemdecl} \begin{itemdescr} @@ -4010,18 +4000,6 @@ \tcode{v.value == 0}. \end{itemdescr} -\indexlibrarymember{operator"!=}{strong_equality}% -\begin{itemdecl} -constexpr bool operator!=(strong_equality v, @\unspec@) noexcept; -constexpr bool operator!=(@\unspec@, strong_equality v) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{v.value != 0}. -\end{itemdescr} - \indexlibrarymember{operator<=>}{strong_equality}% \begin{itemdecl} constexpr strong_equality operator<=>(strong_equality v, @\unspec@) noexcept; @@ -4075,13 +4053,11 @@ // comparisons friend constexpr bool operator==(partial_ordering v, @\unspec@) noexcept; - friend constexpr bool operator!=(partial_ordering v, @\unspec@) noexcept; + friend constexpr bool operator==(partial_ordering v, partial_ordering w) noexcept = default; friend constexpr bool operator< (partial_ordering v, @\unspec@) noexcept; friend constexpr bool operator> (partial_ordering v, @\unspec@) noexcept; friend constexpr bool operator<=(partial_ordering v, @\unspec@) noexcept; friend constexpr bool operator>=(partial_ordering v, @\unspec@) noexcept; - friend constexpr bool operator==(@\unspec@, partial_ordering v) noexcept; - friend constexpr bool operator!=(@\unspec@, partial_ordering v) noexcept; friend constexpr bool operator< (@\unspec@, partial_ordering v) noexcept; friend constexpr bool operator> (@\unspec@, partial_ordering v) noexcept; friend constexpr bool operator<=(@\unspec@, partial_ordering v) noexcept; @@ -4131,13 +4107,11 @@ For \tcode{operator@}, \tcode{v.is_ordered \&\& v.value @ 0}. \end{itemdescr} -\indexlibrarymember{operator==}{partial_ordering}% \indexlibrarymember{operator<}{partial_ordering}% \indexlibrarymember{operator>}{partial_ordering}% \indexlibrarymember{operator<=}{partial_ordering}% \indexlibrarymember{operator>=}{partial_ordering}% \begin{itemdecl} -constexpr bool operator==(@\unspec@, partial_ordering v) noexcept; constexpr bool operator< (@\unspec@, partial_ordering v) noexcept; constexpr bool operator> (@\unspec@, partial_ordering v) noexcept; constexpr bool operator<=(@\unspec@, partial_ordering v) noexcept; @@ -4150,18 +4124,6 @@ For \tcode{operator@}, \tcode{v.is_ordered \&\& 0 @ v.value}. \end{itemdescr} -\indexlibrarymember{operator"!=}{partial_ordering}% -\begin{itemdecl} -constexpr bool operator!=(partial_ordering v, @\unspec@) noexcept; -constexpr bool operator!=(@\unspec@, partial_ordering v) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -For \tcode{operator@}, \tcode{!v.is_ordered || v.value != 0}. -\end{itemdescr} - \indexlibrarymember{operator<=>}{partial_ordering}% \begin{itemdecl} constexpr partial_ordering operator<=>(partial_ordering v, @\unspec@) noexcept; @@ -4217,13 +4179,11 @@ // comparisons friend constexpr bool operator==(weak_ordering v, @\unspec@) noexcept; - friend constexpr bool operator!=(weak_ordering v, @\unspec@) noexcept; + friend constexpr bool operator==(weak_ordering v, weak_ordering w) noexcept = default; friend constexpr bool operator< (weak_ordering v, @\unspec@) noexcept; friend constexpr bool operator> (weak_ordering v, @\unspec@) noexcept; friend constexpr bool operator<=(weak_ordering v, @\unspec@) noexcept; friend constexpr bool operator>=(weak_ordering v, @\unspec@) noexcept; - friend constexpr bool operator==(@\unspec@, weak_ordering v) noexcept; - friend constexpr bool operator!=(@\unspec@, weak_ordering v) noexcept; friend constexpr bool operator< (@\unspec@, weak_ordering v) noexcept; friend constexpr bool operator> (@\unspec@, weak_ordering v) noexcept; friend constexpr bool operator<=(@\unspec@, weak_ordering v) noexcept; @@ -4266,14 +4226,12 @@ \end{itemdescr} \indexlibrarymember{operator==}{weak_ordering}% -\indexlibrarymember{operator"!=}{weak_ordering}% \indexlibrarymember{operator<}{weak_ordering}% \indexlibrarymember{operator>}{weak_ordering}% \indexlibrarymember{operator<=}{weak_ordering}% \indexlibrarymember{operator>=}{weak_ordering}% \begin{itemdecl} constexpr bool operator==(weak_ordering v, @\unspec@) noexcept; -constexpr bool operator!=(weak_ordering v, @\unspec@) noexcept; constexpr bool operator< (weak_ordering v, @\unspec@) noexcept; constexpr bool operator> (weak_ordering v, @\unspec@) noexcept; constexpr bool operator<=(weak_ordering v, @\unspec@) noexcept; @@ -4286,15 +4244,11 @@ \tcode{v.value @ 0} for \tcode{operator@}. \end{itemdescr} -\indexlibrarymember{operator==}{weak_ordering}% -\indexlibrarymember{operator"!=}{weak_ordering}% \indexlibrarymember{operator<}{weak_ordering}% \indexlibrarymember{operator>}{weak_ordering}% \indexlibrarymember{operator<=}{weak_ordering}% \indexlibrarymember{operator>=}{weak_ordering}% \begin{itemdecl} -constexpr bool operator==(@\unspec@, weak_ordering v) noexcept; -constexpr bool operator!=(@\unspec@, weak_ordering v) noexcept; constexpr bool operator< (@\unspec@, weak_ordering v) noexcept; constexpr bool operator> (@\unspec@, weak_ordering v) noexcept; constexpr bool operator<=(@\unspec@, weak_ordering v) noexcept; @@ -4366,13 +4320,11 @@ // comparisons friend constexpr bool operator==(strong_ordering v, @\unspec@) noexcept; - friend constexpr bool operator!=(strong_ordering v, @\unspec@) noexcept; + friend constexpr bool operator==(strong_ordering v, strong_ordering w) noexcept = default; friend constexpr bool operator< (strong_ordering v, @\unspec@) noexcept; friend constexpr bool operator> (strong_ordering v, @\unspec@) noexcept; friend constexpr bool operator<=(strong_ordering v, @\unspec@) noexcept; friend constexpr bool operator>=(strong_ordering v, @\unspec@) noexcept; - friend constexpr bool operator==(@\unspec@, strong_ordering v) noexcept; - friend constexpr bool operator!=(@\unspec@, strong_ordering v) noexcept; friend constexpr bool operator< (@\unspec@, strong_ordering v) noexcept; friend constexpr bool operator> (@\unspec@, strong_ordering v) noexcept; friend constexpr bool operator<=(@\unspec@, strong_ordering v) noexcept; @@ -4442,14 +4394,12 @@ \end{itemdescr} \indexlibrarymember{operator==}{strong_ordering}% -\indexlibrarymember{operator"!=}{strong_ordering}% \indexlibrarymember{operator<}{strong_ordering}% \indexlibrarymember{operator>}{strong_ordering}% \indexlibrarymember{operator<=}{strong_ordering}% \indexlibrarymember{operator>=}{strong_ordering}% \begin{itemdecl} constexpr bool operator==(strong_ordering v, @\unspec@) noexcept; -constexpr bool operator!=(strong_ordering v, @\unspec@) noexcept; constexpr bool operator< (strong_ordering v, @\unspec@) noexcept; constexpr bool operator> (strong_ordering v, @\unspec@) noexcept; constexpr bool operator<=(strong_ordering v, @\unspec@) noexcept; @@ -4462,15 +4412,11 @@ \tcode{v.value @ 0} for \tcode{operator@}. \end{itemdescr} -\indexlibrarymember{operator==}{strong_ordering}% -\indexlibrarymember{operator"!=}{strong_ordering}% \indexlibrarymember{operator<}{strong_ordering}% \indexlibrarymember{operator>}{strong_ordering}% \indexlibrarymember{operator<=}{strong_ordering}% \indexlibrarymember{operator>=}{strong_ordering}% \begin{itemdecl} -constexpr bool operator==(@\unspec@, strong_ordering v) noexcept; -constexpr bool operator!=(@\unspec@, strong_ordering v) noexcept; constexpr bool operator< (@\unspec@, strong_ordering v) noexcept; constexpr bool operator> (@\unspec@, strong_ordering v) noexcept; constexpr bool operator<=(@\unspec@, strong_ordering v) noexcept; @@ -4538,183 +4484,426 @@ \end{note} \end{itemdescr} -\rSec2[cmp.alg]{Comparison algorithms} +\rSec2[cmp.concept]{Concept \tcode{ThreeWayComparable}} -\indexlibrary{\idxcode{strong_order}}% -\begin{itemdecl} -template constexpr strong_ordering strong_order(const T& a, const T& b); -\end{itemdecl} +\begin{codeblock} +template + concept @\placeholder{compares-as}@ = // \expos + Same, Cat>; + +template + concept @\placeholder{partially-ordered-with}@ = // \expos + requires(const remove_reference_t& t, const remove_reference_t& u) { + { t < u } -> Boolean; + { t > u } -> Boolean; + { t <= u } -> Boolean; + { t >= u } -> Boolean; + { u < t } -> Boolean; + { u > t } -> Boolean; + { u <= t } -> Boolean; + { u >= t } -> Boolean; + }; +\end{codeblock} -\begin{itemdescr} \pnum -\effects -Compares two values and produces a result of type \tcode{strong_ordering}: - +Let \tcode{t} and \tcode{u} be +lvalues of types \tcode{const remove_reference_t} and +\tcode{const remove_reference_t}, respectively. +\tcode{T} and \tcode{U} model +\tcode{\placeholder{partially-ordered-with}} only if: \begin{itemize} \item -If \tcode{numeric_limits::is_iec559} is \tcode{true}, -returns a result of type \tcode{strong_ordering} -that is consistent with the \tcode{totalOrder} operation -as specified in ISO/IEC/IEEE 60559. + \tcode{t < u}, + \tcode{t <= u}, + \tcode{t > u}, + \tcode{t >= u}, + \tcode{u < t}, + \tcode{u <= t}, + \tcode{u > t}, and + \tcode{u >= t} + have the same domain. +\item + \tcode{bool(t < u) == bool(u > t)} is \tcode{true}, \item -Otherwise, returns \tcode{a <=> b} -if that expression is well-formed and -convertible to \tcode{strong_ordering}. + \tcode{bool(u < t) == bool(t > u)} is \tcode{true}, \item -Otherwise, if the expression \tcode{a <=> b} is well-formed, -then the function is defined as deleted. + \tcode{bool(t <= u) == bool(u >= t)} is \tcode{true}, and \item -Otherwise, if the expressions \tcode{a == b} and \tcode{a < b} -are each well-formed and convertible to \tcode{bool}, then + \tcode{bool(u <= t) == bool(t >= u)} is \tcode{true}. +\end{itemize} + +\begin{codeblock} +template + concept ThreeWayComparable = + @\placeholder{weakly-equality-comparable-with}@ && + (!ConvertibleTo || @\placeholder{partially-ordered-with}@) && + requires(const remove_reference_t& a, const remove_reference_t& b) { + { a <=> b } -> @\placeholder{compares-as}@; + }; +\end{codeblock} + +\pnum +Let \tcode{a} and \tcode{b} be lvalues +of type \tcode{const remove_reference_t}. +\tcode{T} and \tcode{Cat} +model \tcode{\libconcept{ThreeWayComparable}} only if: \begin{itemize} \item -if \tcode{a == b} is \tcode{true}, -returns \tcode{strong_ordering::equal}; + \tcode{(a <=> b == 0) == bool(a == b)} is \tcode{true}; \item -otherwise, if \tcode{a < b} is \tcode{true}, -returns \tcode{strong_ordering::less}; + \tcode{(a <=> b != 0) == bool(a != b)} is \tcode{true}; \item -otherwise, -returns \tcode{strong_ordering::greater}. -\end{itemize} + \tcode{((a <=> b) <=> 0)} and \tcode{(0 <=> (b <=> a))} are equal; +\item + if \tcode{Cat} is convertible to \tcode{strong_equality}, \tcode{T} models + \libconcept{EqualityComparable}\iref{concept.equalitycomparable}; +\item + if \tcode{Cat} is convertible to \tcode{partial_ordering}: + \begin{itemize} + \item + \tcode{(a <=> b < 0) == bool(a < b)} is \tcode{true}, + \item + \tcode{(a <=> b > 0) == bool(a > b)} is \tcode{true}, + \item + \tcode{(a <=> b <= 0) == bool(a <= b)} is \tcode{true}, and + \item + \tcode{(a <=> b >= 0) == bool(a >= b)} is \tcode{true}; and + \end{itemize} \item -Otherwise, the function is defined as deleted. + If \tcode{Cat} is convertible to \tcode{strong_ordering}, \tcode{T} models + \libconcept{StrictTotallyOrdered}\iref{concept.stricttotallyordered}. \end{itemize} -\end{itemdescr} -\indexlibrary{\idxcode{weak_order}}% -\begin{itemdecl} -template constexpr weak_ordering weak_order(const T& a, const T& b); -\end{itemdecl} +\begin{codeblock} +template + concept ThreeWayComparableWith = + @\placeholder{weakly-equality-comparable-with}@ && + (!ConvertibleTo || @\placeholder{partially-ordered-with}@) && + ThreeWayComparable && + ThreeWayComparable && + CommonReference&, const remove_reference_t&> && + ThreeWayComparable< + common_reference_t&, const remove_reference_t&>, Cat> && + requires(const remove_reference_t& t, const remove_reference_t& u) { + { t <=> u } -> @\placeholder{compares-as}@; + { u <=> t } -> @\placeholder{compares-as}@; + }; +\end{codeblock} -\begin{itemdescr} \pnum -\effects -Compares two values and produces a result of type \tcode{weak_ordering}: - +Let \tcode{t} and \tcode{u} be lvalues +of types \tcode{const remove_reference_t} and +\tcode{const remove_reference_t}, respectively. +Let \tcode{C} be +\tcode{common_reference_t\&, const remove_reference_t\&>}. +\tcode{T}, \tcode{U}, and \tcode{Cat} +model \tcode{\libconcept{ThreeWayComparableWith}} only if: \begin{itemize} \item -Returns \tcode{a <=> b} if that expression is well-formed and -convertible to \tcode{weak_ordering}. + \tcode{t <=> u} and \tcode{u <=> t} have the same domain; \item -Otherwise, if the expression \tcode{a <=> b} is well-formed, -then the function is defined as deleted. + \tcode{((t <=> u) <=> 0)} and \tcode{(0 <=> (u <=> t))} are equal; \item -Otherwise, if the expressions \tcode{a == b} and \tcode{a < b} -are each well-formed and convertible to \tcode{bool}, then -\begin{itemize} + \tcode{(t <=> u == 0) == bool(t == u)} is \tcode{true}; \item -if \tcode{a == b} is \tcode{true}, -returns \tcode{weak_ordering::equivalent}; + \tcode{(t <=> u != 0) == bool(t != u)} is \tcode{true}; \item -otherwise, if \tcode{a < b} is \tcode{true}, -returns \tcode{weak_ordering::less}; + \tcode{Cat(t <=> u) == Cat(C(t) <=> C(u))} is \tcode{true}; \item -otherwise, returns \tcode{weak_ordering::greater}. -\end{itemize} + if \tcode{Cat} is convertible to \tcode{strong_equality}, + \tcode{T} and \tcode{U} model + \tcode{\libconcept{EqualityComparableWith}}\iref{concept.equalitycomparable}; \item -Otherwise, the function is defined as deleted. + if \tcode{Cat} is convertible to \tcode{partial_ordering}: + \begin{itemize} + \item + \tcode{(t <=> u < 0) == bool(t < u)} is \tcode{true}, + \item + \tcode{(t <=> u > 0) == bool(t > u)} is \tcode{true}, + \item + \tcode{(t <=> u <= 0) == bool(t <= u)} is \tcode{true}, + \item + \tcode{(t <=> u >= 0) == bool(t >= u)} is \tcode{true}; and + \end{itemize} +\item + if \tcode{Cat} is convertible to \tcode{strong_ordering}, + \tcode{T} and \tcode{U} model + \tcode{\libconcept{StrictTotallyOrderedWith}}\iref{concept.stricttotallyordered}. \end{itemize} -\end{itemdescr} -\indexlibrary{\idxcode{partial_order}}% +\rSec2[cmp.result]{Result of three-way comparison} + +\pnum +The behavior of a program +that adds specializations for the \tcode{compare_three_way_result} template +defined in this subclause is undefined. + +\pnum +For the \tcode{compare_three_way_result} type trait +applied to the types \tcode{T} and \tcode{U}, +let \tcode{t} and \tcode{u} denote lvalues of types +\tcode{const remove_reference_t} and \tcode{const remove_reference_t}, +respectively. +If the expression \tcode{t <=> u} is well-formed +when treated as an unevaluated operand\iref{expr.context}, +the member \grammarterm{typedef-name} \tcode{type} +denotes the type \tcode{decltype(t <=> u)}. +Otherwise, there is no member \tcode{type}. + +\rSec2[cmp.object]{Class \tcode{compare_three_way}} + +\pnum +In this subclause, \tcode{\placeholdernc{BUILTIN-PTR-THREE-WAY}(T, U)} +for types \tcode{T} and \tcode{U} is a boolean constant expression. +\tcode{\placeholdernc{BUILTIN-PTR-THREE-WAY}(T, U)} is \tcode{true} +if and only if \tcode{<=>} in the expression +\begin{codeblock} +declval() <=> declval() +\end{codeblock} +resolves to a built-in operator comparing pointers. + +\begin{codeblock} +struct compare_three_way { + template + requires ThreeWayComparableWith || @\placeholdernc{BUILTIN-PTR-THREE-WAY}@(T, U) + constexpr auto operator()(T&& t, U&& u) const; + + using is_transparent = @\unspec@; +}; +\end{codeblock} + +\pnum +In addition to being available via inclusion of the \tcode{} header, +the class \tcode{compare_three_way} is available +when the header \tcode{} is included. + \begin{itemdecl} -template constexpr partial_ordering partial_order(const T& a, const T& b); +constexpr auto operator()(T&& t, U&& u) const; \end{itemdecl} \begin{itemdescr} +\pnum +\expects +If the expression \tcode{std::forward(t) <=> std::forward(u)} results in +a call to a built-in operator \tcode{<=>} comparing pointers of type \tcode{P}, +the conversion sequences from both \tcode{T} and \tcode{U} to \tcode{P} +are equality-preserving\iref{concepts.equality}. + \pnum \effects -Compares two values and produces a result of type \tcode{partial_ordering}: +\begin{itemize} +\item + If the expression \tcode{std::forward(t) <=> std::forward(u)} results in + a call to a built-in operator \tcode{<=>} comparing pointers of type \tcode{P}, + returns \tcode{strong_ordering::less} + if (the converted value of) \tcode{t} precedes \tcode{u} + in the implementation-defined strict total order\iref{range.cmp} + over pointers of type \tcode{P}, + \tcode{strong_ordering::greater} + if \tcode{u} precedes \tcode{t}, and + otherwise \tcode{strong_ordering::equal}. +\item + Otherwise, equivalent to: \tcode{return std::forward(t) <=> std::forward(u);} +\end{itemize} +\end{itemdescr} + +\rSec2[cmp.alg]{Comparison algorithms} +\indexlibrary{\idxcode{strong_order}}% +\pnum +The name \tcode{strong_order} denotes +a customization point object\iref{customization.point.object}. +The expression \tcode{strong_order(E, F)} +for some subexpressions \tcode{E} and \tcode{F} +is expression-equivalent\iref{defns.expression-equivalent} to the following: \begin{itemize} \item -Returns \tcode{a <=> b} if that expression is well-formed and -convertible to \tcode{partial_ordering}. + If the decayed types of \tcode{E} and \tcode{F} differ, + \tcode{strong_order(E, F)} is ill-formed. +\item + Otherwise, \tcode{strong_ordering(strong_order(E, F))} + if it is a well-formed expression + with overload resolution performed in a context + that does not include a declaration of \tcode{std::strong_order}. +\item + Otherwise, if the decayed type \tcode{T} of \tcode{E} is + a floating-point type, + yields a value of type \tcode{strong_ordering} + that is consistent with the ordering + observed by \tcode{T}’s comparison operators, and + if \tcode{numeric_limits::is_iec559} is \tcode{true}, + is additionally consistent with the \tcode{totalOrder} operation + as specified in ISO/IEC/IEEE 60599. \item -Otherwise, if the expression \tcode{a <=> b} is well-formed, -then the function is defined as deleted. + Otherwise, \tcode{strong_ordering(E <=> F)} if it is a well-formed expression. \item -Otherwise, if the expressions \tcode{a == b} and \tcode{a < b} -are each well-formed and convertible to \tcode{bool}, then + Otherwise, \tcode{strong_order(E, F)} is ill-formed. + \begin{note} + This case can result in substitution failure + when \tcode{strong_order(E, F)} appears in the immediate context + of a template instantiation. + \end{note} +\end{itemize} + +\indexlibrary{\idxcode{weak_order}}% +\pnum +The name \tcode{weak_order} denotes +a customization point object\iref{customization.point.object}. +The expression \tcode{weak_order(E, F)} +for some subexpressions \tcode{E} and \tcode{F} +is expression-equivalent\iref{defns.expression-equivalent} to the following: \begin{itemize} \item -if \tcode{a == b} is \tcode{true}, -returns \tcode{partial_ordering::equivalent}; + If the decayed types of \tcode{E} and \tcode{F} differ, + \tcode{weak_order(E, F)} is ill-formed. \item -otherwise, if \tcode{a < b} is \tcode{true}, -returns \tcode{partial_ordering::less}; + Otherwise, \tcode{weak_ordering(weak_order(E, F))} + if it is a well-formed expression + with overload resolution performed in a context + that does not include a declaration of \tcode{std::weak_order}. \item -otherwise, returns \tcode{partial_ordering::greater}. -\end{itemize} + Otherwise, if the decayed type \tcode{T} of \tcode{E} + is a floating-point type, + yields a value of type \tcode{weak_ordering} + that is consistent with the ordering + observed by \tcode{T}’s comparison operators and \tcode{strong_order}, and + if \tcode{numeric_limits::is_iec559} is \tcode{true}, + is additionally consistent with the following equivalence classes, + ordered from lesser to greater: + \begin{itemize} + \item together, all negative NaN values; + \item negative infinity; + \item each normal negative value; + \item each subnormal negative value; + \item together, both zero values; + \item each subnormal positive value; + \item each normal positive value; + \item positive infinity; + \item together, all positive NaN values. + \end{itemize} +\item + Otherwise, \tcode{weak_ordering(E <=> F)} if it is a well-formed expression. \item -Otherwise, the function is defined as deleted. + Otherwise, \tcode{weak_ordering(strong_order(E, F))} + if it is a well-formed expression. +\item + Otherwise, \tcode{weak_order(E, F)} is ill-formed. + \begin{note} + This case can result in substitution failure + when \tcode{std::weak_order(E, F)} appears in the immediate context + of a template instantiation. + \end{note} \end{itemize} -\end{itemdescr} - -\indexlibrary{\idxcode{strong_equal}}% -\begin{itemdecl} -template constexpr strong_equality strong_equal(const T& a, const T& b); -\end{itemdecl} -\begin{itemdescr} +\indexlibrary{\idxcode{partial_order}}% \pnum -\effects -Compares two values and produces a result of type \tcode{strong_equality}: - +The name \tcode{partial_order} denotes +a customization point object\iref{customization.point.object}. +The expression \tcode{partial_order(E, F)} +for some subexpressions \tcode{E} and \tcode{F} +is expression-equivalent\iref{defns.expression-equivalent} to the following: \begin{itemize} \item -Returns \tcode{a <=> b} if that expression is well-formed and -convertible to \tcode{strong_equality}. + If the decayed types of \tcode{E} and \tcode{F} differ, + \tcode{partial_order(E, F)} is ill-formed. \item -Otherwise, if the expression \tcode{a <=> b} is well-formed, -then the function is defined as deleted. + Otherwise, \tcode{partial_ordering(partial_order(E, F))} + if it is a well-formed expression + with overload resolution performed in a context + that does not include a declaration of \tcode{std::partial_order}. \item -Otherwise, if the expression \tcode{a == b} -is well-formed and convertible to \tcode{bool}, then -\begin{itemize} + Otherwise, \tcode{partial_ordering(E <=> F)} + if it is a well-formed expression. \item -if \tcode{a == b} is \tcode{true}, -returns \tcode{strong_equality::equal}; + Otherwise, \tcode{partial_ordering(weak_order(E, F))} + if it is a well-formed expression. \item -otherwise, returns \tcode{strong_equality::nonequal}. + Otherwise, \tcode{partial_order(E, F)} is ill-formed. + \begin{note} + This case can result in substitution failure + when \tcode{std::partial_order(E, F)} + appears in the immediate context of a template instantiation. +\end{note} \end{itemize} + +\indexlibrary{\idxcode{compare_strong_order_fallback}}% +\pnum +The name \tcode{compare_strong_order_fallback} +denotes a customization point object\iref{customization.point.object}. +The expression \tcode{compare_strong_order_fallback(E, F)} +for some subexpressions \tcode{E} and {F} +is expression-equivalent\iref{defns.expression-equivalent} to: +\begin{itemize} +\item + If the decayed types of \tcode{E} and \tcode{F} differ, + \tcode{compare_strong_order_fallback(E, F)} is ill-formed. +\item + Otherwise, \tcode{strong_order(E, F)} if it is a well-formed expression. +\item + Otherwise, if the expressions \tcode{E == F} and \tcode{E < F} + are both well-formed and convertible to \tcode{bool}, +\begin{codeblock} +E == F ? strong_ordering::equal : +E < F ? strong_ordering::less : + strong_ordering::greater +\end{codeblock} +except that \tcode{E} and \tcode{F} are evaluated only once. \item -Otherwise, the function is defined as deleted. +Otherwise, \tcode{compare_strong_order_fallback(E, F)} is ill-formed. \end{itemize} -\end{itemdescr} -\indexlibrary{\idxcode{weak_equal}}% -\begin{itemdecl} -template constexpr weak_equality weak_equal(const T& a, const T& b); -\end{itemdecl} - -\begin{itemdescr} +\indexlibrary{\idxcode{compare_weak_order_fallback}}% \pnum -\effects -Compares two values and produces a result of type \tcode{weak_equality}: - +The name \tcode{compare_weak_order_fallback} denotes +a customization point object\iref{customization.point.object}. +The expression \tcode{compare_weak_order_fallback(E, F)} +for some subexpressions \tcode{E} and \tcode{F} +is expression-equivalent\iref{defns.expression-equivalent} to: \begin{itemize} \item -Returns \tcode{a <=> b} if that expression is well-formed and -convertible to \tcode{weak_equality}. + If the decayed types of \tcode{E} and \tcode{F} differ, + \tcode{compare_weak_order_fallback(E, F)} is ill-formed. \item -Otherwise, if the expression \tcode{a <=> b} is well-formed, -then the function is defined as deleted. + Otherwise, \tcode{weak_order(E, F)} if it is a well-formed expression. +\item + Otherwise, if the expressions \tcode{E == F} and \tcode{E < F} + are both well-formed and convertible to \tcode{bool}, +\begin{codeblock} +E == F ? weak_ordering::equal : +E < F ? weak_ordering::less : + weak_ordering::greater +\end{codeblock} +except that \tcode{E} and \tcode{F} are evaluated only once. \item -Otherwise, if the expression \tcode{a == b} -is well-formed and convertible to \tcode{bool}, then + Otherwise, \tcode{compare_weak_order_fallback(E, F)} is ill-formed. +\end{itemize} + +\indexlibrary{\idxcode{compare_partial_order_fallback}}% +\pnum +The name \tcode{compare_partial_order_fallback} denotes +a customization point object\iref{customization.point.object}. +The expression \tcode{compare_partial_order_fallback(E, F)} +for some subexpressions \tcode{E} and \tcode{F} +is expression-equivalent\iref{defns.expression-equivalent} to: \begin{itemize} \item -if \tcode{a == b} is \tcode{true}, -returns \tcode{weak_equality::equivalent}; + If the decayed types of \tcode{E} and \tcode{F} differ, + \tcode{compare_partial_order_fallback(E, F)} is ill-formed. \item -otherwise, returns \tcode{weak_equality::nonequivalent}. -\end{itemize} + Otherwise, \tcode{partial_order(E, F)} if it is a well-formed expression. \item -Otherwise, the function is defined as deleted. + Otherwise, if the expressions \tcode{E == F} and \tcode{E < F} + are both well-formed and convertible to \tcode{bool}, +\begin{codeblock} +E == F ? partial_ordering::equivalent : +E < F ? partial_ordering::less : +F < E ? partial_ordering::greater : + partial_ordering::unordered +\end{codeblock} +except that \tcode{E} and \tcode{F} are evaluated only once. +\item + Otherwise, \tcode{compare_partial_order_fallback(E, F)} is ill-formed. \end{itemize} -\end{itemdescr} \rSec1[support.coroutine]{Coroutines} @@ -4742,11 +4931,7 @@ // \ref{coroutine.handle.compare}, comparison operators constexpr bool operator==(coroutine_handle<> x, coroutine_handle<> y) noexcept; - constexpr bool operator!=(coroutine_handle<> x, coroutine_handle<> y) noexcept; - constexpr bool operator<(coroutine_handle<> x, coroutine_handle<> y) noexcept; - constexpr bool operator>(coroutine_handle<> x, coroutine_handle<> y) noexcept; - constexpr bool operator<=(coroutine_handle<> x, coroutine_handle<> y) noexcept; - constexpr bool operator>=(coroutine_handle<> x, coroutine_handle<> y) noexcept; + constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept; // \ref{coroutine.handle.hash}, hash support template struct hash; @@ -5022,16 +5207,13 @@ \pnum \returns \tcode{x.address() == y.address()}. \end{itemdescr} -\indexlibrarymember{operator<}{coroutine_handle}% -\indexlibrarymember{operator>}{coroutine_handle}% -\indexlibrarymember{operator<=}{coroutine_handle}% -\indexlibrarymember{operator>=}{coroutine_handle}% +\indexlibrarymember{operator<=>}{coroutine_handle}% \begin{itemdecl} -constexpr bool operator<(coroutine_handle<> x, coroutine_handle<> y) noexcept; +constexpr strong_ordering operator<=>(coroutine_handle<> x, coroutine_handle<> y) noexcept; \end{itemdecl} \begin{itemdescr} -\pnum \returns \tcode{less<>()(x.address(), y.address())}. +\pnum \returns \tcode{compare_three_way()(x.address(), y.address())}. \end{itemdescr} \rSec3[coroutine.handle.hash]{Hash support} diff --git a/source/threads.tex b/source/threads.tex index fe4b671934..b6cfb1fdc9 100644 --- a/source/threads.tex +++ b/source/threads.tex @@ -360,11 +360,7 @@ }; bool operator==(thread::id x, thread::id y) noexcept; - bool operator!=(thread::id x, thread::id y) noexcept; - bool operator<(thread::id x, thread::id y) noexcept; - bool operator>(thread::id x, thread::id y) noexcept; - bool operator<=(thread::id x, thread::id y) noexcept; - bool operator>=(thread::id x, thread::id y) noexcept; + strong_ordering operator<=>(thread::id x, thread::id y) noexcept; template basic_ostream& @@ -415,51 +411,23 @@ execution. \end{itemdescr} -\indexlibrarymember{operator"!=}{thread::id}% +\indexlibrarymember{operator<=>}{thread::id}% \begin{itemdecl} -bool operator!=(thread::id x, thread::id y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(x == y)} -\end{itemdescr} - -\indexlibrarymember{operator<}{thread::id}% -\begin{itemdecl} -bool operator<(thread::id x, thread::id y) noexcept; +strong_ordering operator<=>(thread::id x, thread::id y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns A value such that \tcode{operator<} is a total ordering as described in~\ref{alg.sorting}. -\end{itemdescr} - -\indexlibrarymember{operator>}{thread::id}% -\begin{itemdecl} -bool operator>(thread::id x, thread::id y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{y < x}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{thread::id}% -\begin{itemdecl} -bool operator<=(thread::id x, thread::id y) noexcept; -\end{itemdecl} +Let $P(\tcode{x}, \tcode{y})$ be +an unspecified total ordering over \tcode{thread::id} +as described in \ref{alg.sorting}. -\begin{itemdescr} \pnum -\returns \tcode{!(y < x)}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{thread::id}% -\begin{itemdecl} -bool operator>=(thread::id x, thread::id y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(x < y)}. +\returns +\tcode{strong_ordering::less} if $P(\tcode{x}, \tcode{y})$ is \tcode{true}. +Otherwise, \tcode{strong_ordering::greater} +if $P(\tcode{y}, \tcode{x})$ is \tcode{true}. +Otherwise, \tcode{strong_ordering::equal}. \end{itemdescr} \indexlibrarymember{operator<<}{thread::id}% diff --git a/source/time.tex b/source/time.tex index e02751fe43..e3135ff0f6 100644 --- a/source/time.tex +++ b/source/time.tex @@ -121,9 +121,6 @@ template constexpr bool operator==(const duration& lhs, const duration& rhs); - template - constexpr bool operator!=(const duration& lhs, - const duration& rhs); template constexpr bool operator< (const duration& lhs, const duration& rhs); @@ -136,6 +133,10 @@ template constexpr bool operator>=(const duration& lhs, const duration& rhs); + template + requires @\seebelow@ + constexpr auto operator<=>(const duration& lhs, + const duration& rhs); // \ref{time.duration.cast}, \tcode{duration_cast} template @@ -194,9 +195,6 @@ template constexpr bool operator==(const time_point& lhs, const time_point& rhs); - template - constexpr bool operator!=(const time_point& lhs, - const time_point& rhs); template constexpr bool operator< (const time_point& lhs, const time_point& rhs); @@ -209,6 +207,9 @@ template constexpr bool operator>=(const time_point& lhs, const time_point& rhs); + template Duration2> + constexpr auto operator<=>(const time_point& lhs, + const time_point& rhs); // \ref{time.point.cast}, \tcode{time_point_cast} template @@ -357,11 +358,7 @@ class day; constexpr bool operator==(const day& x, const day& y) noexcept; - constexpr bool operator!=(const day& x, const day& y) noexcept; - constexpr bool operator< (const day& x, const day& y) noexcept; - constexpr bool operator> (const day& x, const day& y) noexcept; - constexpr bool operator<=(const day& x, const day& y) noexcept; - constexpr bool operator>=(const day& x, const day& y) noexcept; + constexpr strong_ordering operator<=>(const day& x, const day& y) noexcept; constexpr day operator+(const day& x, const days& y) noexcept; constexpr day operator+(const days& x, const day& y) noexcept; @@ -381,11 +378,7 @@ class month; constexpr bool operator==(const month& x, const month& y) noexcept; - constexpr bool operator!=(const month& x, const month& y) noexcept; - constexpr bool operator< (const month& x, const month& y) noexcept; - constexpr bool operator> (const month& x, const month& y) noexcept; - constexpr bool operator<=(const month& x, const month& y) noexcept; - constexpr bool operator>=(const month& x, const month& y) noexcept; + constexpr strong_ordering operator<=>(const month& x, const month& y) noexcept; constexpr month operator+(const month& x, const months& y) noexcept; constexpr month operator+(const months& x, const month& y) noexcept; @@ -405,11 +398,7 @@ class year; constexpr bool operator==(const year& x, const year& y) noexcept; - constexpr bool operator!=(const year& x, const year& y) noexcept; - constexpr bool operator< (const year& x, const year& y) noexcept; - constexpr bool operator> (const year& x, const year& y) noexcept; - constexpr bool operator<=(const year& x, const year& y) noexcept; - constexpr bool operator>=(const year& x, const year& y) noexcept; + constexpr strong_ordering operator<=>(const year& x, const year& y) noexcept; constexpr year operator+(const year& x, const years& y) noexcept; constexpr year operator+(const years& x, const year& y) noexcept; @@ -430,7 +419,6 @@ class weekday; constexpr bool operator==(const weekday& x, const weekday& y) noexcept; - constexpr bool operator!=(const weekday& x, const weekday& y) noexcept; constexpr weekday operator+(const weekday& x, const days& y) noexcept; constexpr weekday operator+(const days& x, const weekday& y) noexcept; @@ -451,7 +439,6 @@ class weekday_indexed; constexpr bool operator==(const weekday_indexed& x, const weekday_indexed& y) noexcept; - constexpr bool operator!=(const weekday_indexed& x, const weekday_indexed& y) noexcept; template basic_ostream& @@ -461,7 +448,6 @@ class weekday_last; constexpr bool operator==(const weekday_last& x, const weekday_last& y) noexcept; - constexpr bool operator!=(const weekday_last& x, const weekday_last& y) noexcept; template basic_ostream& @@ -471,11 +457,7 @@ class month_day; constexpr bool operator==(const month_day& x, const month_day& y) noexcept; - constexpr bool operator!=(const month_day& x, const month_day& y) noexcept; - constexpr bool operator< (const month_day& x, const month_day& y) noexcept; - constexpr bool operator> (const month_day& x, const month_day& y) noexcept; - constexpr bool operator<=(const month_day& x, const month_day& y) noexcept; - constexpr bool operator>=(const month_day& x, const month_day& y) noexcept; + constexpr strong_ordering operator<=>(const month_day& x, const month_day& y) noexcept; template basic_ostream& @@ -491,11 +473,8 @@ class month_day_last; constexpr bool operator==(const month_day_last& x, const month_day_last& y) noexcept; - constexpr bool operator!=(const month_day_last& x, const month_day_last& y) noexcept; - constexpr bool operator< (const month_day_last& x, const month_day_last& y) noexcept; - constexpr bool operator> (const month_day_last& x, const month_day_last& y) noexcept; - constexpr bool operator<=(const month_day_last& x, const month_day_last& y) noexcept; - constexpr bool operator>=(const month_day_last& x, const month_day_last& y) noexcept; + constexpr strong_ordering operator<=>(const month_day_last& x, + const month_day_last& y) noexcept; template basic_ostream& @@ -505,7 +484,6 @@ class month_weekday; constexpr bool operator==(const month_weekday& x, const month_weekday& y) noexcept; - constexpr bool operator!=(const month_weekday& x, const month_weekday& y) noexcept; template basic_ostream& @@ -515,7 +493,6 @@ class month_weekday_last; constexpr bool operator==(const month_weekday_last& x, const month_weekday_last& y) noexcept; - constexpr bool operator!=(const month_weekday_last& x, const month_weekday_last& y) noexcept; template basic_ostream& @@ -525,11 +502,7 @@ class year_month; constexpr bool operator==(const year_month& x, const year_month& y) noexcept; - constexpr bool operator!=(const year_month& x, const year_month& y) noexcept; - constexpr bool operator< (const year_month& x, const year_month& y) noexcept; - constexpr bool operator> (const year_month& x, const year_month& y) noexcept; - constexpr bool operator<=(const year_month& x, const year_month& y) noexcept; - constexpr bool operator>=(const year_month& x, const year_month& y) noexcept; + constexpr strong_ordering operator<=>(const year_month& x, const year_month& y) noexcept; constexpr year_month operator+(const year_month& ym, const months& dm) noexcept; constexpr year_month operator+(const months& dm, const year_month& ym) noexcept; @@ -553,11 +526,8 @@ class year_month_day; constexpr bool operator==(const year_month_day& x, const year_month_day& y) noexcept; - constexpr bool operator!=(const year_month_day& x, const year_month_day& y) noexcept; - constexpr bool operator< (const year_month_day& x, const year_month_day& y) noexcept; - constexpr bool operator> (const year_month_day& x, const year_month_day& y) noexcept; - constexpr bool operator<=(const year_month_day& x, const year_month_day& y) noexcept; - constexpr bool operator>=(const year_month_day& x, const year_month_day& y) noexcept; + constexpr strong_ordering operator<=>(const year_month_day& x, + const year_month_day& y) noexcept; constexpr year_month_day operator+(const year_month_day& ymd, const months& dm) noexcept; constexpr year_month_day operator+(const months& dm, const year_month_day& ymd) noexcept; @@ -582,16 +552,8 @@ constexpr bool operator==(const year_month_day_last& x, const year_month_day_last& y) noexcept; - constexpr bool operator!=(const year_month_day_last& x, - const year_month_day_last& y) noexcept; - constexpr bool operator< (const year_month_day_last& x, - const year_month_day_last& y) noexcept; - constexpr bool operator> (const year_month_day_last& x, - const year_month_day_last& y) noexcept; - constexpr bool operator<=(const year_month_day_last& x, - const year_month_day_last& y) noexcept; - constexpr bool operator>=(const year_month_day_last& x, - const year_month_day_last& y) noexcept; + constexpr strong_ordering operator<=>(const year_month_day_last& x, + const year_month_day_last& y) noexcept; constexpr year_month_day_last operator+(const year_month_day_last& ymdl, const months& dm) noexcept; @@ -615,8 +577,6 @@ constexpr bool operator==(const year_month_weekday& x, const year_month_weekday& y) noexcept; - constexpr bool operator!=(const year_month_weekday& x, - const year_month_weekday& y) noexcept; constexpr year_month_weekday operator+(const year_month_weekday& ymwd, const months& dm) noexcept; @@ -640,8 +600,6 @@ constexpr bool operator==(const year_month_weekday_last& x, const year_month_weekday_last& y) noexcept; - constexpr bool operator!=(const year_month_weekday_last& x, - const year_month_weekday_last& y) noexcept; constexpr year_month_weekday_last operator+(const year_month_weekday_last& ymwdl, const months& dm) noexcept; @@ -789,12 +747,7 @@ class time_zone; bool operator==(const time_zone& x, const time_zone& y) noexcept; - bool operator!=(const time_zone& x, const time_zone& y) noexcept; - - bool operator<(const time_zone& x, const time_zone& y) noexcept; - bool operator>(const time_zone& x, const time_zone& y) noexcept; - bool operator<=(const time_zone& x, const time_zone& y) noexcept; - bool operator>=(const time_zone& x, const time_zone& y) noexcept; + strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; // \ref{time.zone.zonedtraits}, class template \tcode{zoned_traits} template struct zoned_traits; @@ -808,10 +761,6 @@ bool operator==(const zoned_time& x, const zoned_time& y); - template - bool operator!=(const zoned_time& x, - const zoned_time& y); - template basic_ostream& operator<<(basic_ostream& os, @@ -821,20 +770,10 @@ class leap; bool operator==(const leap& x, const leap& y); - bool operator!=(const leap& x, const leap& y); - bool operator< (const leap& x, const leap& y); - bool operator> (const leap& x, const leap& y); - bool operator<=(const leap& x, const leap& y); - bool operator>=(const leap& x, const leap& y); + strong_ordering operator<=>(const leap& x, const leap& y); template bool operator==(const leap& x, const sys_time& y); - template - bool operator==(const sys_time& x, const leap& y); - template - bool operator!=(const leap& x, const sys_time& y); - template - bool operator!=(const sys_time& x, const leap& y); template bool operator< (const leap& x, const sys_time& y); template @@ -851,16 +790,14 @@ bool operator>=(const leap& x, const sys_time& y); template bool operator>=(const sys_time& x, const leap& y); + template Duration> + auto operator<=>(const leap& x, const sys_time& y); // \ref{time.zone.link}, class \tcode{link} class link; bool operator==(const link& x, const link& y); - bool operator!=(const link& x, const link& y); - bool operator< (const link& x, const link& y); - bool operator> (const link& x, const link& y); - bool operator<=(const link& x, const link& y); - bool operator>=(const link& x, const link& y); + strong_ordering operator<=>(const link& x, const link& y); // \ref{time.format}, formatting template struct @\placeholder{local-time-format-t}@; // \expos @@ -1713,18 +1650,6 @@ \returns \tcode{CT(lhs).count() == CT(rhs).count()}. \end{itemdescr} -\indexlibrarymember{operator"!=}{duration}% -\begin{itemdecl} -template - constexpr bool operator!=(const duration& lhs, - const duration& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(lhs == rhs)}. -\end{itemdescr} - \indexlibrarymember{operator<}{duration}% \begin{itemdecl} template @@ -1773,6 +1698,19 @@ \returns \tcode{!(lhs < rhs)}. \end{itemdescr} +\indexlibrarymember{operator<=>}{duration}% +\begin{itemdecl} +template + requires ThreeWayComparable + constexpr auto operator<=>(const duration& lhs, + const duration& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns \tcode{CT(lhs).count() <=> CT(rhs).count()}. +\end{itemdescr} + \rSec2[time.duration.cast]{\tcode{duration_cast}} \indexlibrary{\idxcode{duration}!\idxcode{duration_cast}}% @@ -2368,18 +2306,6 @@ \returns \tcode{lhs.time_since_epoch() == rhs.time_since_epoch()}. \end{itemdescr} -\indexlibrarymember{operator"!=}{time_point}% -\begin{itemdecl} -template - constexpr bool operator!=(const time_point& lhs, - const time_point& rhs); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(lhs == rhs)}. -\end{itemdescr} - \indexlibrarymember{operator<}{time_point}% \begin{itemdecl} template @@ -2428,6 +2354,19 @@ \returns \tcode{!(lhs < rhs)}. \end{itemdescr} +\indexlibrarymember{operator>=}{time_point}% +\begin{itemdecl} +template Duration2> + constexpr auto operator<=>(const time_point& lhs, + const time_point& rhs); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns \tcode{lhs.time_since_epoch() <=> rhs.time_since_epoch()}. +\end{itemdescr} + \rSec2[time.point.cast]{\tcode{time_point_cast}} \indexlibrary{\idxcode{time_point}!\idxcode{time_point_cast}}% @@ -3940,14 +3879,14 @@ \returns \tcode{unsigned\{x\} == unsigned\{y\}}. \end{itemdescr} -\indexlibrarymember{operator<}{day}% +\indexlibrarymember{operator<=>}{day}% \begin{itemdecl} -constexpr bool operator<(const day& x, const day& y) noexcept; +onstexpr strong_ordering operator<=>(const day& x, const day& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{unsigned\{x\} < unsigned\{y\}}. +\returns \tcode{unsigned\{x\} <=> unsigned\{y\}}. \end{itemdescr} \indexlibrarymember{operator+}{day}% @@ -4212,14 +4151,14 @@ \returns \tcode{unsigned\{x\} == unsigned\{y\}}. \end{itemdescr} -\indexlibrarymember{operator<}{month}% +\indexlibrarymember{operator<=>}{month}% \begin{itemdecl} -constexpr bool operator<(const month& x, const month& y) noexcept; +constexpr strong_ordering operator<=>(const month& x, const month& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{unsigned\{x\} < unsigned\{y\}}. +\returns \tcode{unsigned\{x\} <=> unsigned\{y\}}. \end{itemdescr} \indexlibrarymember{operator+}{month}% @@ -4554,14 +4493,14 @@ \returns \tcode{int\{x\} == int\{y\}}. \end{itemdescr} -\indexlibrarymember{operator<}{year}% +\indexlibrarymember{operator<=>}{year}% \begin{itemdecl} -constexpr bool operator<(const year& x, const year& y) noexcept; +constexpr strong_ordering operator<=>(const year& x, const year& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{int\{x\} < int\{y\}}. +\returns \tcode{int\{x\} <=> int\{y\}}. \end{itemdescr} \indexlibrarymember{operator+}{year}% @@ -5329,17 +5268,19 @@ \returns \tcode{x.month() == y.month() \&\& x.day() == y.day()}. \end{itemdescr} -\indexlibrarymember{operator<}{month_day}% +\indexlibrarymember{operator<=>}{month_day}% \begin{itemdecl} -constexpr bool operator<(const month_day& x, const month_day& y) noexcept; +constexpr strong_ordering operator<=>(const month_day& x, const month_day& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -If \tcode{x.month() < y.month()} returns \tcode{true}. -Otherwise, if \tcode{x.month() > y.month()} returns \tcode{false}. -Otherwise, returns \tcode{x.day() < y.day()}. +\effects +Equivalent to: +\begin{codeblock} +if (auto c = x.month() <=> y.month(); c != 0) return c; +return x.day() <=> y.day(); +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator<<}{month_day}% @@ -5465,14 +5406,14 @@ \returns \tcode{x.month() == y.month()}. \end{itemdescr} -\indexlibrarymember{operator<}{month_day_last}% +\indexlibrarymember{operator<=>}{month_day_last}% \begin{itemdecl} -constexpr bool operator<(const month_day_last& x, const month_day_last& y) noexcept; +constexpr strong_ordering operator<=>(const month_day_last& x, const month_day_last& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{x.month() < y.month()}. +\returns \tcode{x.month() <=> y.month()}. \end{itemdescr} \indexlibrarymember{operator<<}{month_day_last}% @@ -5861,17 +5802,19 @@ \returns \tcode{x.year() == y.year() \&\& x.month() == y.month()}. \end{itemdescr} -\indexlibrarymember{operator<}{year_month}% +\indexlibrarymember{operator<=>}{year_month}% \begin{itemdecl} -constexpr bool operator<(const year_month& x, const year_month& y) noexcept; +constexpr strong_ordering operator<=>(const year_month& x, const year_month& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -If \tcode{x.year() < y.year()} returns \tcode{true}. -Otherwise, if \tcode{x.year() > y.year()} returns \tcode{false}. -Otherwise, returns \tcode{x.month() < y.month()}. +\effects +Equivalent to: +\begin{codeblock} +if (auto c = x.year() <=> y.year(); c != 0) return c; +return x.month() <=> y.month(); +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator+}{year_month}% @@ -6271,19 +6214,20 @@ \returns \tcode{x.year() == y.year() \&\& x.month() == y.month() \&\& x.day() == y.day()}. \end{itemdescr} -\indexlibrarymember{operator<}{year_month_day}% +\indexlibrarymember{operator<=>}{year_month_day}% \begin{itemdecl} -constexpr bool operator<(const year_month_day& x, const year_month_day& y) noexcept; +constexpr strong_ordering operator<=>(const year_month_day& x, const year_month_day& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -If \tcode{x.year() < y.year()}, returns \tcode{true}. -Otherwise, if \tcode{x.year() > y.year()}, returns \tcode{false}. -Otherwise, if \tcode{x.month() < y.month()}, returns \tcode{true}. -Otherwise, if \tcode{x.month() > y.month()}, returns \tcode{false}. -Otherwise, returns \tcode{x.day() < y.day()}. +\effects +Equivalent to: +\begin{codeblock} +if (auto c = x.year() <=> y.year(); c != 0) return c; +if (auto c = x.month() <=> y.month(); c != 0) return c; +return x.day() <=> y.day(); +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator+}{year_month_day}% @@ -6611,17 +6555,20 @@ \returns \tcode{x.year() == y.year() \&\& x.month_day_last() == y.month_day_last()}. \end{itemdescr} -\indexlibrarymember{operator<}{year_month_day_last}% +\indexlibrarymember{operator<=>}{year_month_day_last}% \begin{itemdecl} -constexpr bool operator<(const year_month_day_last& x, const year_month_day_last& y) noexcept; +constexpr strong_ordering operator<=>(const year_month_day_last& x, + const year_month_day_last& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns -If \tcode{x.year() < y.year()}, returns \tcode{true}. -Otherwise, if \tcode{x.year() > y.year()}, returns \tcode{false}. -Otherwise, returns \tcode{x.month_day_last() < y.month_day_last()}. +\effects +Equivalent to: +\begin{codeblock} +if (auto c = x.year() <=> y.year(); c != 0) return c; +return x.month_day_last() <=> y.month_day_last(); +\end{codeblock} \end{itemdescr} \indexlibrarymember{operator+}{year_month_day_last}% @@ -8942,14 +8889,14 @@ \returns \tcode{x.name() == y.name()}. \end{itemdescr} -\indexlibrarymember{operator<}{time_zone}% +\indexlibrarymember{operator<=>}{time_zone}% \begin{itemdecl} -bool operator<(const time_zone& x, const time_zone& y) noexcept; +strong_ordering operator<=>(const time_zone& x, const time_zone& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{x.name() < y.name()}. +\returns \tcode{x.name() <=> y.name()}. \end{itemdescr} \rSec2[time.zone.zonedtraits]{Class template \tcode{zoned_traits}} @@ -9476,18 +9423,6 @@ \returns \tcode{x.zone_ == y.zone_ \&\& x.tp_ == y.tp_}. \end{itemdescr} -\indexlibrarymember{operator"!=}{zoned_time}% -\begin{itemdecl} -template - bool operator!=(const zoned_time& x, - const zoned_time& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(x == y)}. -\end{itemdescr} - \indexlibrarymember{operator<<}{zoned_time}% \begin{itemdecl} template @@ -9597,14 +9532,14 @@ \returns \tcode{x.date() == y.date()}. \end{itemdescr} -\indexlibrarymember{operator<}{leap}% +\indexlibrarymember{operator<=>}{leap}% \begin{itemdecl} -constexpr bool operator<(const leap& x, const leap& y) noexcept; +constexpr strong_ordering operator<=>(const leap& x, const leap& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{x.date() < y.date()}. +\returns \tcode{x.date() <=> y.date()}. \end{itemdescr} \indexlibrarymember{operator==}{leap}% @@ -9619,42 +9554,6 @@ \returns \tcode{x.date() == y}. \end{itemdescr} -\indexlibrarymember{operator==}{leap}% -\indexlibrarymember{operator==}{sys_time}% -\begin{itemdecl} -template - constexpr bool operator==(const sys_time& x, const leap& y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{y == x}. -\end{itemdescr} - -\indexlibrarymember{operator"!=}{leap}% -\indexlibrarymember{operator"!=}{sys_time}% -\begin{itemdecl} -template - constexpr bool operator!=(const leap& x, const sys_time& y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(x == y)}. -\end{itemdescr} - -\indexlibrarymember{operator"!=}{leap}% -\indexlibrarymember{operator"!=}{sys_time}% -\begin{itemdecl} -template - constexpr bool operator!=(const sys_time& x, const leap& y) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(x == y)}. -\end{itemdescr} - \indexlibrarymember{operator<}{leap}% \indexlibrarymember{operator<}{sys_time}% \begin{itemdecl} @@ -9751,6 +9650,18 @@ \returns \tcode{!(x < y)}. \end{itemdescr} +\indexlibrarymember{operator<=>}{leap}% +\indexlibrarymember{operator<=>}{sys_time}% +\begin{itemdecl} +template Duration> + constexpr auto operator<=>(const leap& x, const sys_time& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns \tcode{x.date() <=> y}. +\end{itemdescr} + \rSec2[time.zone.link]{Class \tcode{link}} \rSec3[time.zone.link.overview]{Overview} @@ -9812,14 +9723,14 @@ \returns \tcode{x.name() == y.name()}. \end{itemdescr} -\indexlibrarymember{operator<}{link}% +\indexlibrarymember{operator<=>}{link}% \begin{itemdecl} -bool operator<(const link& x, const link& y) noexcept; +strong_ordering operator<=>(const link& x, const link& y) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{x.name() < y.name()}. +\returns \tcode{x.name() <=> y.name()}. \end{itemdescr} \rSec1[time.format]{Formatting} diff --git a/source/utilities.tex b/source/utilities.tex index f47d8fbd5f..aa0ef50f3a 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -101,19 +101,6 @@ struct pair; // \ref{pairs.spec}, pair specialized algorithms - template - constexpr bool operator==(const pair&, const pair&); - template - constexpr bool operator!=(const pair&, const pair&); - template - constexpr bool operator< (const pair&, const pair&); - template - constexpr bool operator> (const pair&, const pair&); - template - constexpr bool operator<=(const pair&, const pair&); - template - constexpr bool operator>=(const pair&, const pair&); - template constexpr void swap(pair& x, pair& y) noexcept(noexcept(x.swap(y))); @@ -500,6 +487,15 @@ constexpr pair& operator=(pair&& p); constexpr void swap(pair& p) noexcept(@\seebelow@); + + // \ref{pairs.spec}, pair specialized algorithms + friend constexpr bool operator==(const pair&, const pair&) = default; + friend constexpr bool operator==(const pair& x, const pair& y) + requires (is_reference_v || is_reference_v) + { return x.first == y.first && x.second == y.second; } + friend constexpr common_comparison_category_t<@\placeholder{synth-three-way-result}@, + @\placeholder{synth-three-way-result}@> + operator<=>(const pair& x, const pair& y) { @\seebelow@ } }; template @@ -764,75 +760,23 @@ \rSec2[pairs.spec]{Specialized algorithms} -\indexlibrarymember{operator==}{pair}% -\begin{itemdecl} -template - constexpr bool operator==(const pair& x, const pair& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x.first == y.first \&\& x.second == y.second}. -\end{itemdescr} - -\indexlibrarymember{operator"!=}{pair}% -\begin{itemdecl} -template - constexpr bool operator!=(const pair& x, const pair& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(x == y)}. -\end{itemdescr} - -\indexlibrarymember{operator<}{pair}% -\begin{itemdecl} -template - constexpr bool operator<(const pair& x, const pair& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{x.first < y.first || (!(y.first < x.first) \&\& x.second < y.second)}. -\end{itemdescr} - -\indexlibrarymember{operator>}{pair}% -\begin{itemdecl} -template - constexpr bool operator>(const pair& x, const pair& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{y < x}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{pair}% -\begin{itemdecl} -template - constexpr bool operator<=(const pair& x, const pair& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(y < x)}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{pair}% +\indexlibrarymember{operator<=>}{pair}% \begin{itemdecl} -template - constexpr bool operator>=(const pair& x, const pair& y); +friend constexpr + common_comparison_category_t<@\placeholder{synth-three-way-result}@, @\placeholder{synth-three-way-result}@> + operator<=>(const pair& x, const pair& y); \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{!(x < y)}. +\effects +Equivalent to: +\begin{codeblock} +if (auto c = @\placeholdernc{synth-three-way}@(x.first, y.first); c != 0) return c; +return @\placeholdernc{synth-three-way}@(x.second, y.second); +\end{codeblock} \end{itemdescr} - \indexlibrary{\idxcode{swap}!\idxcode{pair}}% \begin{itemdecl} template @@ -1062,15 +1006,8 @@ template constexpr bool operator==(const tuple&, const tuple&); template - constexpr bool operator!=(const tuple&, const tuple&); - template - constexpr bool operator<(const tuple&, const tuple&); - template - constexpr bool operator>(const tuple&, const tuple&); - template - constexpr bool operator<=(const tuple&, const tuple&); - template - constexpr bool operator>=(const tuple&, const tuple&); + constexpr common_comparison_category_t<@\placeholder{synth-three-way-result}@...> + operator<=>(const tuple&, const tuple&); // \ref{tuple.traits}, allocator-related traits template @@ -2007,77 +1944,37 @@ \tcode{false}. \end{itemdescr} -\indexlibrarymember{operator"!=}{tuple}% -\begin{itemdecl} -template - constexpr bool operator!=(const tuple& t, const tuple& u); -\end{itemdecl} -\begin{itemdescr} -\pnum\returns \tcode{!(t == u)}. -\end{itemdescr} - -\indexlibrarymember{operator<}{tuple}% +\indexlibrarymember{operator<=>}{tuple}% \begin{itemdecl} template - constexpr bool operator<(const tuple& t, const tuple& u); + constexpr common_comparison_category_t<@\placeholder{synth-three-way-result}@...> + operator<=>(const tuple& t, const tuple& u); \end{itemdecl} \begin{itemdescr} \pnum -\requires For all \tcode{i}, -where \tcode{0 <= i} and -\tcode{i < sizeof...(TTypes)}, both \tcode{get(t) < get(u)} -and \tcode{get(u) < get(t)} -are valid expressions returning types that are -convertible to \tcode{bool}. -\tcode{sizeof...(TTypes)} \tcode{==} -\tcode{sizeof...(UTypes)}. - -\pnum\returns The result of a lexicographical comparison -between \tcode{t} and \tcode{u}. The result is defined -as: \tcode{(bool)(get<0>(t) < get<0>(u)) || -(!(bool)(get<0>(u) < get<0>(t)) \&\& t$_{\mathrm{tail}}$ < -u$_{\mathrm{tail}}$)}, where \tcode{r$_{\mathrm{tail}}$} for some -tuple \tcode{r} is a tuple containing all but the first element -of \tcode{r}. For any two zero-length tuples \tcode{e} -and \tcode{f}, \tcode{e < f} returns \tcode{false}. -\end{itemdescr} - -\indexlibrarymember{operator>}{tuple}% -\begin{itemdecl} -template - constexpr bool operator>(const tuple& t, const tuple& u); -\end{itemdecl} -\begin{itemdescr} -\pnum\returns \tcode{u < t}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{tuple}% -\begin{itemdecl} -template - constexpr bool operator<=(const tuple& t, const tuple& u); -\end{itemdecl} -\begin{itemdescr} -\pnum\returns \tcode{!(u < t)}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{tuple}% -\begin{itemdecl} -template - constexpr bool operator>=(const tuple& t, const tuple& u); -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{!(t < u)}. +\effects +Performs a lexicographical comparison between \tcode{t} and \tcode{u}. +For any two zero-length tuples \tcode{t} and \tcode{u}, +\tcode{t <=> u} returns \tcode{strong_ordering::equal}. +Otherwise, equivalent to: +\begin{codeblock} +if (auto c = @\placeholder{synth-three-way}@(get<0>(t), get<0>(u)); c != 0) return c; +return @$\tcode{t}_\mathrm{tail}$@ <=> @$\tcode{u}_\mathrm{tail}$@; +\end{codeblock} +where $\tcode{r}_\mathrm{tail}$ for some tuple \tcode{r} +is a tuple containing all but the first element of \tcode{r}. \end{itemdescr} -\pnum \begin{note} The above definitions for comparison functions -do not require \tcode{t$_{\mathrm{tail}}$} +\pnum +\begin{note} +The above definition does not require \tcode{t$_{\mathrm{tail}}$} (or \tcode{u$_{\mathrm{tail}}$}) to be constructed. It may not even be possible, as \tcode{t} and \tcode{u} are not required to be copy constructible. Also, all comparison functions are short circuited; they do not perform element accesses beyond what is required to determine the -result of the comparison. \end{note} +result of the comparison. +\end{note} \rSec3[tuple.traits]{Tuple traits} @@ -2164,20 +2061,14 @@ constexpr bool operator<=(const optional&, const optional&); template constexpr bool operator>=(const optional&, const optional&); + template U> + constexpr compare_three_way_result_t + operator<=>(const optional&, const optional&); // \ref{optional.nullops}, comparison with \tcode{nullopt} template constexpr bool operator==(const optional&, nullopt_t) noexcept; - template constexpr bool operator==(nullopt_t, const optional&) noexcept; - template constexpr bool operator!=(const optional&, nullopt_t) noexcept; - template constexpr bool operator!=(nullopt_t, const optional&) noexcept; - template constexpr bool operator<(const optional&, nullopt_t) noexcept; - template constexpr bool operator<(nullopt_t, const optional&) noexcept; - template constexpr bool operator>(const optional&, nullopt_t) noexcept; - template constexpr bool operator>(nullopt_t, const optional&) noexcept; - template constexpr bool operator<=(const optional&, nullopt_t) noexcept; - template constexpr bool operator<=(nullopt_t, const optional&) noexcept; - template constexpr bool operator>=(const optional&, nullopt_t) noexcept; - template constexpr bool operator>=(nullopt_t, const optional&) noexcept; + template + constexpr strong_ordering operator<=>(const optional&, nullopt_t) noexcept; // \ref{optional.comp.with.t}, comparison with \tcode{T} template constexpr bool operator==(const optional&, const U&); @@ -2192,6 +2083,9 @@ template constexpr bool operator<=(const T&, const optional&); template constexpr bool operator>=(const optional&, const U&); template constexpr bool operator>=(const T&, const optional&); + template U> + constexpr compare_three_way_result_t + operator<=>(const optional&, const U&); // \ref{optional.specalg}, specialized algorithms template @@ -3310,79 +3204,30 @@ shall be constexpr functions. \end{itemdescr} -\rSec2[optional.nullops]{Comparison with \tcode{nullopt}} - -\indexlibrarymember{operator==}{optional}% +\indexlibrarymember{operator<=>}{optional}% \begin{itemdecl} -template constexpr bool operator==(const optional& x, nullopt_t) noexcept; -template constexpr bool operator==(nullopt_t, const optional& x) noexcept; +template U> + constexpr compare_three_way_result_t + operator<=>(const optional& x, const optional& y); \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{!x}. -\end{itemdescr} - -\indexlibrarymember{operator"!=}{optional}% -\begin{itemdecl} -template constexpr bool operator!=(const optional& x, nullopt_t) noexcept; -template constexpr bool operator!=(nullopt_t, const optional& x) noexcept; -\end{itemdecl} +If \tcode{x \&\& y}, \tcode{*x <=> *y}; otherwise \tcode{bool(x) <=> bool(y)}. -\begin{itemdescr} -\pnum -\returns -\tcode{bool(x)}. -\end{itemdescr} - -\indexlibrarymember{operator<}{optional}% -\begin{itemdecl} -template constexpr bool operator<(const optional& x, nullopt_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} \pnum -\returns -\tcode{false}. -\end{itemdescr} - -\indexlibrarymember{operator<}{optional}% -\begin{itemdecl} -template constexpr bool operator<(nullopt_t, const optional& x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{bool(x)}. -\end{itemdescr} - -\indexlibrarymember{operator>}{optional}% -\begin{itemdecl} -template constexpr bool operator>(const optional& x, nullopt_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{bool(x)}. +\remarks +Specializations of this function template +for which \tcode{*x <=> *y} is a core constant expression +shall be constexpr functions. \end{itemdescr} -\indexlibrarymember{operator>}{optional}% -\begin{itemdecl} -template constexpr bool operator>(nullopt_t, const optional& x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{false}. -\end{itemdescr} +\rSec2[optional.nullops]{Comparison with \tcode{nullopt}} -\indexlibrarymember{operator<=}{optional}% +\indexlibrarymember{operator==}{optional}% \begin{itemdecl} -template constexpr bool operator<=(const optional& x, nullopt_t) noexcept; +template constexpr bool operator==(const optional& x, nullopt_t) noexcept; \end{itemdecl} \begin{itemdescr} @@ -3391,37 +3236,15 @@ \tcode{!x}. \end{itemdescr} -\indexlibrarymember{operator<=}{optional}% -\begin{itemdecl} -template constexpr bool operator<=(nullopt_t, const optional& x) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{optional}% -\begin{itemdecl} -template constexpr bool operator>=(const optional& x, nullopt_t) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true}. -\end{itemdescr} - -\indexlibrarymember{operator>=}{optional}% +\indexlibrarymember{operator<=>}{optional}% \begin{itemdecl} -template constexpr bool operator>=(nullopt_t, const optional& x) noexcept; +template constexpr strong_ordering operator<=>(const optional& x, nullopt_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -\tcode{!x}. +\tcode{bool(x) <=> false}. \end{itemdescr} \rSec2[optional.comp.with.t]{Comparison with \tcode{T}} @@ -3621,6 +3444,18 @@ Equivalent to: \tcode{return bool(x) ?\ v >= *x :\ true;} \end{itemdescr} +\indexlibrarymember{operator<=>}{optional}% +\begin{itemdecl} +template U> + constexpr compare_three_way_result_t + operator<=>(const optional& x, const U& v); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return bool(x) ?\ *x <=> v :\ strong_ordering::less;} +\end{itemdescr} \rSec2[optional.specalg]{Specialized algorithms} @@ -3783,6 +3618,9 @@ constexpr bool operator<=(const variant&, const variant&); template constexpr bool operator>=(const variant&, const variant&); + template requires (ThreeWayComparable && ...) + constexpr common_comparison_category_t...> + operator<=>(const variant&, const variant&); // \ref{variant.visit}, visitation template @@ -3795,11 +3633,7 @@ // \ref{variant.monostate.relops}, \tcode{monostate} relational operators constexpr bool operator==(monostate, monostate) noexcept; - constexpr bool operator!=(monostate, monostate) noexcept; - constexpr bool operator<(monostate, monostate) noexcept; - constexpr bool operator>(monostate, monostate) noexcept; - constexpr bool operator<=(monostate, monostate) noexcept; - constexpr bool operator>=(monostate, monostate) noexcept; + constexpr strong_ordering operator<=>(monostate, monostate) noexcept; // \ref{variant.specalg}, specialized algorithms template @@ -4876,6 +4710,28 @@ otherwise \tcode{get<$i$>(v) >= get<$i$>(w)} with $i$ being \tcode{v.index()}. \end{itemdescr} +\indexlibrarymember{operator<=>}{variant}% +\begin{itemdecl} +template requires (ThreeWayComparable && ...) + constexpr common_comparison_category_t...> + operator<=>(const variant& v, const variant& w); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (v.valueless_by_exception() && w.valueless_by_exception()) + return strong_ordering::equal; +if (v.valueless_by_exception()) return strong_ordering::less; +if (w.valueless_by_exception()) return strong_ordering::greater; +if (auto c = v.index() <=> w.index(); c != 0) return c; +return get<@$i$@>(v) <=> get<@$i$@>(w); +\end{codeblock} +with $i$ being \tcode{v.index()}. +\end{itemdescr} + \rSec2[variant.visit]{Visitation} \indexlibrary{\idxcode{visit}}% @@ -4945,26 +4801,20 @@ \rSec2[variant.monostate.relops]{\tcode{monostate} relational operators} \indexlibrary{\idxcode{operator==}!\idxcode{monostate}}% -\indexlibrary{\idxcode{operator"!=}!\idxcode{monostate}}% -\indexlibrary{\idxcode{operator<}!\idxcode{monostate}}% -\indexlibrary{\idxcode{operator>}!\idxcode{monostate}}% -\indexlibrary{\idxcode{operator<=}!\idxcode{monostate}}% -\indexlibrary{\idxcode{operator>=}!\idxcode{monostate}}% +\indexlibrary{\idxcode{operator<=>}!\idxcode{monostate}}% \begin{itemdecl} constexpr bool operator==(monostate, monostate) noexcept { return true; } -constexpr bool operator!=(monostate, monostate) noexcept { return false; } -constexpr bool operator<(monostate, monostate) noexcept { return false; } -constexpr bool operator>(monostate, monostate) noexcept { return false; } -constexpr bool operator<=(monostate, monostate) noexcept { return true; } -constexpr bool operator>=(monostate, monostate) noexcept { return true; } +constexpr strong_ordering operator<=>(monostate, monostate) noexcept +{ return strong_ordering::equal; } \end{itemdecl} \begin{itemdescr} \pnum -\begin{note} \tcode{monostate} objects have only a single state; they thus always compare equal.\end{note} +\begin{note} +\tcode{monostate} objects have only a single state; they thus always compare equal. +\end{note} \end{itemdescr} - \rSec2[variant.specalg]{Specialized algorithms} \indexlibrary{\idxcode{swap}!\idxcode{variant}}% @@ -5755,7 +5605,6 @@ size_t count() const noexcept; constexpr size_t size() const noexcept; bool operator==(const bitset& rhs) const noexcept; - bool operator!=(const bitset& rhs) const noexcept; bool test(size_t pos) const; bool all() const noexcept; bool any() const noexcept; @@ -6270,18 +6119,6 @@ equals the value of the corresponding bit in \tcode{rhs}. \end{itemdescr} -\indexlibrarymember{operator"!=}{bitset}% -\begin{itemdecl} -bool operator!=(const bitset& rhs) const noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{true} if -\tcode{!(*this == rhs)}. -\end{itemdescr} - \indexlibrarymember{test}{bitset}% \begin{itemdecl} bool test(size_t pos) const; @@ -6608,8 +6445,6 @@ template class allocator; template constexpr bool operator==(const allocator&, const allocator&) noexcept; - template - constexpr bool operator!=(const allocator&, const allocator&) noexcept; // \ref{specialized.algorithms}, specialized algorithms // \ref{special.mem.concepts}, special memory concepts @@ -6838,8 +6673,6 @@ template bool operator==(const unique_ptr& x, const unique_ptr& y); - template - bool operator!=(const unique_ptr& x, const unique_ptr& y); template bool operator<(const unique_ptr& x, const unique_ptr& y); template @@ -6848,15 +6681,15 @@ bool operator<=(const unique_ptr& x, const unique_ptr& y); template bool operator>=(const unique_ptr& x, const unique_ptr& y); + template + requires ThreeWayComparableWith::pointer, + typename unique_ptr::pointer> + compare_three_way_result_t::pointer, + typename unique_ptr::pointer> + operator<=>(const unique_ptr& x, const unique_ptr& y); template bool operator==(const unique_ptr& x, nullptr_t) noexcept; - template - bool operator==(nullptr_t, const unique_ptr& y) noexcept; - template - bool operator!=(const unique_ptr& x, nullptr_t) noexcept; - template - bool operator!=(nullptr_t, const unique_ptr& y) noexcept; template bool operator<(const unique_ptr& x, nullptr_t); template @@ -6873,6 +6706,10 @@ bool operator>=(const unique_ptr& x, nullptr_t); template bool operator>=(nullptr_t, const unique_ptr& y); + template + requires ThreeWayComparableWith::pointer, nullptr_t> + compare_three_way_result_t::pointer, nullptr_t> + operator<=>(const unique_ptr& x, nullptr_t); template basic_ostream& operator<<(basic_ostream& os, const unique_ptr& p); @@ -6924,40 +6761,12 @@ template bool operator==(const shared_ptr& a, const shared_ptr& b) noexcept; template - bool operator!=(const shared_ptr& a, const shared_ptr& b) noexcept; - template - bool operator<(const shared_ptr& a, const shared_ptr& b) noexcept; - template - bool operator>(const shared_ptr& a, const shared_ptr& b) noexcept; - template - bool operator<=(const shared_ptr& a, const shared_ptr& b) noexcept; - template - bool operator>=(const shared_ptr& a, const shared_ptr& b) noexcept; + strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; template bool operator==(const shared_ptr& x, nullptr_t) noexcept; template - bool operator==(nullptr_t, const shared_ptr& y) noexcept; - template - bool operator!=(const shared_ptr& x, nullptr_t) noexcept; - template - bool operator!=(nullptr_t, const shared_ptr& y) noexcept; - template - bool operator<(const shared_ptr& x, nullptr_t) noexcept; - template - bool operator<(nullptr_t, const shared_ptr& y) noexcept; - template - bool operator>(const shared_ptr& x, nullptr_t) noexcept; - template - bool operator>(nullptr_t, const shared_ptr& y) noexcept; - template - bool operator<=(const shared_ptr& x, nullptr_t) noexcept; - template - bool operator<=(nullptr_t, const shared_ptr& y) noexcept; - template - bool operator>=(const shared_ptr& x, nullptr_t) noexcept; - template - bool operator>=(nullptr_t, const shared_ptr& y) noexcept; + strong_ordering operator<=>(const shared_ptr& x, nullptr_t) noexcept; // \ref{util.smartptr.shared.spec}, \tcode{shared_ptr} specialized algorithms template @@ -8034,18 +7843,6 @@ \tcode{true}. \end{itemdescr} -\indexlibrarymember{operator"!=}{allocator}% -\begin{itemdecl} -template - constexpr bool operator!=(const allocator&, const allocator&) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{false}. -\end{itemdescr} - \rSec2[specialized.algorithms]{Specialized algorithms} \pnum @@ -9817,17 +9614,6 @@ \returns \tcode{x.get() == y.get()}. \end{itemdescr} -\indexlibrarymember{operator"!=}{unique_ptr}% -\begin{itemdecl} -template - bool operator!=(const unique_ptr& x, const unique_ptr& y); -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{x.get() != y.get()}. -\end{itemdescr} - \indexlibrarymember{operator<}{unique_ptr}% \begin{itemdecl} template @@ -9887,30 +9673,31 @@ \returns \tcode{!(x < y)}. \end{itemdescr} -\indexlibrarymember{operator==}{unique_ptr}% +\indexlibrarymember{operator<=>}{unique_ptr}% \begin{itemdecl} -template - bool operator==(const unique_ptr& x, nullptr_t) noexcept; -template - bool operator==(nullptr_t, const unique_ptr& x) noexcept; +template + requires ThreeWayComparableWith::pointer, + typename unique_ptr::pointer> + compare_three_way_result_t::pointer, + typename unique_ptr::pointer> + operator<=>(const unique_ptr& x, const unique_ptr& y); \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{!x}. +\returns +\tcode{compare_three_way()(x.get(), y.get())}. \end{itemdescr} -\indexlibrarymember{operator"!=}{unique_ptr}% +\indexlibrarymember{operator==}{unique_ptr}% \begin{itemdecl} template - bool operator!=(const unique_ptr& x, nullptr_t) noexcept; -template - bool operator!=(nullptr_t, const unique_ptr& x) noexcept; + bool operator==(const unique_ptr& x, nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum -\returns \tcode{(bool)x}. +\returns \tcode{!x}. \end{itemdescr} \indexlibrarymember{operator<}{unique_ptr}% @@ -9984,6 +9771,20 @@ The second function template returns \tcode{!(nullptr < x)}. \end{itemdescr} +\indexlibrarymember{operator<=>}{unique_ptr}% +\begin{itemdecl} +template + requires ThreeWayComparableWith::pointer, nullptr_t> + compare_three_way_result_t::pointer, nullptr_t> + operator<=>(const unique_ptr& x, nullptr_t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{compare_three_way()(x.get(), nullptr)}. +\end{itemdescr} + \rSec3[unique.ptr.io]{I/O} \indexlibrarymember{operator<<}{unique_ptr}% @@ -10992,29 +10793,10 @@ \returns \tcode{a.get() == b.get()}. \end{itemdescr} -\indexlibrarymember{operator<}{shared_ptr}% -\begin{itemdecl} -template - bool operator<(const shared_ptr& a, const shared_ptr& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{less<>()(a.get(), b.get())}. - -\pnum -\begin{note} -Defining a comparison function allows \tcode{shared_ptr} objects to be -used as keys in associative containers. -\end{note} -\end{itemdescr} - \indexlibrarymember{operator==}{shared_ptr}% \begin{itemdecl} template bool operator==(const shared_ptr& a, nullptr_t) noexcept; -template - bool operator==(nullptr_t, const shared_ptr& a) noexcept; \end{itemdecl} \begin{itemdescr} @@ -11022,83 +10804,34 @@ \returns \tcode{!a}. \end{itemdescr} -\indexlibrarymember{operator"!=}{shared_ptr}% -\begin{itemdecl} -template - bool operator!=(const shared_ptr& a, nullptr_t) noexcept; -template - bool operator!=(nullptr_t, const shared_ptr& a) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{(bool)a}. -\end{itemdescr} - -\indexlibrarymember{operator<}{shared_ptr}% -\begin{itemdecl} -template - bool operator<(const shared_ptr& a, nullptr_t) noexcept; -template - bool operator<(nullptr_t, const shared_ptr& a) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -The first function template returns -\begin{codeblock} -less::element_type*>()(a.get(), nullptr) -\end{codeblock} -The second function template returns -\begin{codeblock} -less::element_type*>()(nullptr, a.get()) -\end{codeblock} -\end{itemdescr} - -\indexlibrarymember{operator>}{shared_ptr}% +\indexlibrarymember{operator<=>}{shared_ptr}% \begin{itemdecl} -template - bool operator>(const shared_ptr& a, nullptr_t) noexcept; -template - bool operator>(nullptr_t, const shared_ptr& a) noexcept; +template + strong_ordering operator<=>(const shared_ptr& a, const shared_ptr& b) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -The first function template returns \tcode{nullptr < a}. -The second function template returns \tcode{a < nullptr}. -\end{itemdescr} - -\indexlibrarymember{operator<=}{shared_ptr}% -\begin{itemdecl} -template - bool operator<=(const shared_ptr& a, nullptr_t) noexcept; -template - bool operator<=(nullptr_t, const shared_ptr& a) noexcept; -\end{itemdecl} +\tcode{compare_three_way()(a.get(), b.get())}. -\begin{itemdescr} \pnum -\returns -The first function template returns \tcode{!(nullptr < a)}. -The second function template returns \tcode{!(a < nullptr)}. +\begin{note} +Defining a comparison function allows \tcode{shared_ptr} objects +to be used as keys in associative containers. +\end{note} \end{itemdescr} -\indexlibrarymember{operator>=}{shared_ptr}% +\indexlibrarymember{operator<=>}{shared_ptr}% \begin{itemdecl} template - bool operator>=(const shared_ptr& a, nullptr_t) noexcept; -template - bool operator>=(nullptr_t, const shared_ptr& a) noexcept; + strong_ordering operator<=>(const shared_ptr& a, nullptr_t) noexcept; \end{itemdecl} \begin{itemdescr} \pnum \returns -The first function template returns \tcode{!(a < nullptr)}. -The second function template returns \tcode{!(nullptr < a)}. +\tcode{compare_three_way()(a.get(), nullptr)}. \end{itemdescr} \rSec3[util.smartptr.shared.spec]{Specialized algorithms} @@ -12339,7 +12072,6 @@ class memory_resource; bool operator==(const memory_resource& a, const memory_resource& b) noexcept; - bool operator!=(const memory_resource& a, const memory_resource& b) noexcept; // \ref{mem.poly.allocator.class}, class template \tcode{polymorphic_allocator} template class polymorphic_allocator; @@ -12347,9 +12079,6 @@ template bool operator==(const polymorphic_allocator& a, const polymorphic_allocator& b) noexcept; - template - bool operator!=(const polymorphic_allocator& a, - const polymorphic_allocator& b) noexcept; // \ref{mem.res.global}, global memory resources memory_resource* new_delete_resource() noexcept; @@ -12520,17 +12249,6 @@ \tcode{\&a == \&b || a.is_equal(b)}. \end{itemdescr} -\indexlibrarymember{operator"!=}{memory_resource}% -\begin{itemdecl} -bool operator!=(const memory_resource& a, const memory_resource& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!(a == b)}. -\end{itemdescr} - \rSec2[mem.poly.allocator.class]{Class template \tcode{polymorphic_allocator}} \pnum @@ -12871,20 +12589,6 @@ \tcode{*a.resource() == *b.resource()}. \end{itemdescr} -\indexlibrarymember{operator"!=}{polymorphic_allocator}% -\begin{itemdecl} -template - bool operator!=(const polymorphic_allocator& a, - const polymorphic_allocator& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns -\tcode{!(a == b)}. -\end{itemdescr} - - \rSec2[mem.res.global]{Access to program-wide \tcode{memory_resource} objects} \indexlibrary{\idxcode{new_delete_resource}}% @@ -13504,9 +13208,6 @@ template bool operator==(const scoped_allocator_adaptor& a, const scoped_allocator_adaptor& b) noexcept; - template - bool operator!=(const scoped_allocator_adaptor& a, - const scoped_allocator_adaptor& b) noexcept; } \end{codeblock} @@ -13920,18 +13621,6 @@ \end{codeblock} \end{itemdescr} -\indexlibrarymember{operator"!=}{scoped_allocator_adaptor}% -\begin{itemdecl} -template - bool operator!=(const scoped_allocator_adaptor& a, - const scoped_allocator_adaptor& b) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum -\returns \tcode{!(a == b)}. -\end{itemdescr} - \rSec1[function.objects]{Function objects} \pnum @@ -14064,12 +13753,6 @@ template bool operator==(const function&, nullptr_t) noexcept; - template - bool operator==(nullptr_t, const function&) noexcept; - template - bool operator!=(const function&, nullptr_t) noexcept; - template - bool operator!=(nullptr_t, const function&) noexcept; // \ref{func.search}, searchers template> @@ -14973,23 +14656,24 @@ \rSec2[range.cmp]{Concept-constrained comparisons} \pnum -In this subclause, \tcode{\placeholdernc{BUILTIN_PTR_CMP}(T, $op$, U)} for types \tcode{T} +In this subclause, \tcode{\placeholdernc{BUILTIN-PTR-CMP}(T, $op$, U)} for types \tcode{T} and \tcode{U} and where $op$ is an equality\iref{expr.eq} or relational operator\iref{expr.rel} is a boolean constant expression. -\tcode{\placeholdernc{BUILTIN_PTR_CMP}(T, $op$, U)} is \tcode{true} if and only if $op$ +\tcode{\placeholdernc{BUILTIN-PTR-CMP}(T, $op$, U)} is \tcode{true} if and only if $op$ in the expression \tcode{declval() $op$ declval()} resolves to a built-in operator comparing pointers. \pnum There is an implementation-defined strict total ordering over all pointer values of a given type. This total ordering is consistent with the partial order imposed -by the builtin operators \tcode{<}, \tcode{>}, \tcode{<=}, and \tcode{>=}. +by the builtin operators \tcode{<}, \tcode{>}, \tcode{<=}, \tcode{>=}, and +\tcode{<=>}. \indexlibrary{\idxcode{equal_to}}% \begin{itemdecl} struct ranges::equal_to { template - requires EqualityComparableWith || @\placeholdernc{BUILTIN_PTR_CMP}@(T, ==, U) + requires EqualityComparableWith || @\placeholdernc{BUILTIN-PTR-CMP}@(T, ==, U) constexpr bool operator()(T&& t, U&& u) const; using is_transparent = @\unspecnc@; @@ -15024,7 +14708,7 @@ \begin{itemdecl} struct ranges::not_equal_to { template - requires EqualityComparableWith || @\placeholdernc{BUILTIN_PTR_CMP}@(T, ==, U) + requires EqualityComparableWith || @\placeholdernc{BUILTIN-PTR-CMP}@(T, ==, U) constexpr bool operator()(T&& t, U&& u) const; using is_transparent = @\unspecnc@; @@ -15043,7 +14727,7 @@ \begin{itemdecl} struct ranges::greater { template - requires StrictTotallyOrderedWith || @\placeholdernc{BUILTIN_PTR_CMP}@(U, <, T) + requires StrictTotallyOrderedWith || @\placeholdernc{BUILTIN-PTR-CMP}@(U, <, T) constexpr bool operator()(T&& t, U&& u) const; using is_transparent = @\unspecnc@; @@ -15062,7 +14746,7 @@ \begin{itemdecl} struct ranges::less { template - requires StrictTotallyOrderedWith || @\placeholdernc{BUILTIN_PTR_CMP}@(T, <, U) + requires StrictTotallyOrderedWith || @\placeholdernc{BUILTIN-PTR-CMP}@(T, <, U) constexpr bool operator()(T&& t, U&& u) const; using is_transparent = @\unspecnc@; @@ -15103,7 +14787,7 @@ \begin{itemdecl} struct ranges::greater_equal { template - requires StrictTotallyOrderedWith || @\placeholdernc{BUILTIN_PTR_CMP}@(T, <, U) + requires StrictTotallyOrderedWith || @\placeholdernc{BUILTIN-PTR-CMP}@(T, <, U) constexpr bool operator()(T&& t, U&& u) const; using is_transparent = @\unspecnc@; @@ -15122,7 +14806,7 @@ \begin{itemdecl} struct ranges::less_equal { template - requires StrictTotallyOrderedWith || @\placeholdernc{BUILTIN_PTR_CMP}@(U, <, T) + requires StrictTotallyOrderedWith || @\placeholdernc{BUILTIN-PTR-CMP}@(U, <, T) constexpr bool operator()(T&& t, U&& u) const; using is_transparent = @\unspecnc@; @@ -15851,19 +15535,10 @@ template function(F) -> function<@\seebelow@>; - // \ref{func.wrap.func.nullptr}, Null pointer comparisons + // \ref{func.wrap.func.nullptr}, null pointer comparison functions template bool operator==(const function&, nullptr_t) noexcept; - template - bool operator==(nullptr_t, const function&) noexcept; - - template - bool operator!=(const function&, nullptr_t) noexcept; - - template - bool operator!=(nullptr_t, const function&) noexcept; - // \ref{func.wrap.func.alg}, specialized algorithms template void swap(function&, function&) noexcept; @@ -16168,26 +15843,12 @@ \begin{itemdecl} template bool operator==(const function& f, nullptr_t) noexcept; -template - bool operator==(nullptr_t, const function& f) noexcept; \end{itemdecl} \begin{itemdescr} \pnum\returns \tcode{!f}. \end{itemdescr} -\indexlibrarymember{operator"!=}{function}% -\begin{itemdecl} -template - bool operator!=(const function& f, nullptr_t) noexcept; -template - bool operator!=(nullptr_t, const function& f) noexcept; -\end{itemdecl} - -\begin{itemdescr} -\pnum\returns \tcode{(bool)f}. -\end{itemdescr} - \rSec4[func.wrap.func.alg]{Specialized algorithms} \indexlibrarymember{swap}{function}% @@ -16720,6 +16381,8 @@ template struct has_unique_object_representations; + template struct has_strong_structural_equality; + // \ref{meta.unary.prop.query}, type property queries template struct alignment_of; template struct rank; @@ -16997,6 +16660,10 @@ inline constexpr bool has_unique_object_representations_v = has_unique_object_representations::value; + template + inline constexpr bool has_strong_structural_equality_v + = has_strong_structural_equality::value; + // \ref{meta.unary.prop.query}, type property queries template inline constexpr size_t alignment_of_v = alignment_of::value; @@ -17634,6 +17301,14 @@ \tcode{T} shall be a complete type, \cv{}~\tcode{void}, or an array of unknown bound. \\ \rowsep +\indexlibrary{\idxcode{has_strong_structural_equality}}% +\tcode{template}\br + \tcode{struct has_strong_structural_equality;} & + The type \tcode{T} has + strong structural equality\iref{class.compare.default}. & + \tcode{T} shall be a complete type, \cv{} \tcode{void}, or + an array of unknown bound. \\ \rowsep + \end{libreqtab3b} \pnum @@ -18394,6 +18069,10 @@ None of the following will apply if there is a specialization \tcode{common_type}. \end{note} + \item Otherwise, if both \tcode{D1} and \tcode{D2} denote + comparison category types\iref{cmp.categories.pre}, + let \tcode{C} denote the common comparison type\iref{class.spaceship} + of \tcode{D1} and \tcode{D2}. \item Otherwise, if \begin{codeblock} decay_t() : declval())> @@ -18968,11 +18647,11 @@ public: type_index(const type_info& rhs) noexcept; bool operator==(const type_index& rhs) const noexcept; - bool operator!=(const type_index& rhs) const noexcept; bool operator< (const type_index& rhs) const noexcept; bool operator> (const type_index& rhs) const noexcept; bool operator<=(const type_index& rhs) const noexcept; bool operator>=(const type_index& rhs) const noexcept; + strong_ordering operator<=>(const type_index& rhs) const noexcept; size_t hash_code() const noexcept; const char* name() const noexcept; @@ -19013,11 +18692,6 @@ \returns \tcode{*target == *rhs.target}. \end{itemdescr} -\indexlibrarymember{operator"!=}{type_index}% -\begin{itemdecl} -bool operator!=(const type_index& rhs) const noexcept; -\end{itemdecl} - \begin{itemdescr} \pnum \returns \tcode{*target != *rhs.target}. @@ -19063,6 +18737,22 @@ \returns \tcode{!target->before(*rhs.target)}. \end{itemdescr} +\indexlibrarymember{operator<=>}{type_index}% +\begin{itemdecl} +strong_ordering operator<=>(const type_index& rhs) const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if (*target == *rhs.target) return strong_ordering::equal; +if (target->before(*rhs.target)) return strong_ordering::less; +return strong_ordering::greater; +\end{codeblock} +\end{itemdescr} + \indexlibrarymember{hash_code}{type_index}% \begin{itemdecl} size_t hash_code() const noexcept; @@ -19319,6 +19009,7 @@ struct to_chars_result { char* ptr; errc ec; + friend bool operator==(const to_chars_result&, const to_chars_result&) = default; }; to_chars_result to_chars(char* first, char* last, @\seebelow@ value, int base = 10); @@ -19346,6 +19037,7 @@ struct from_chars_result { const char* ptr; errc ec; + friend bool operator==(const from_chars_result&, const from_chars_result&) = default; }; from_chars_result from_chars(const char* first, const char* last,