[libcxx-commits] [libcxx] 882fba9 - [libc++][ranges] Implement LWG-3865 Sorting a range of pairs
Igor Zhukov via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Mar 9 18:04:09 PST 2023
Author: Igor Zhukov
Date: 2023-03-10T09:01:52+07:00
New Revision: 882fba9ff275f724a998facba12ad8fc22ab54a3
URL: https://github.com/llvm/llvm-project/commit/882fba9ff275f724a998facba12ad8fc22ab54a3
DIFF: https://github.com/llvm/llvm-project/commit/882fba9ff275f724a998facba12ad8fc22ab54a3.diff
LOG: [libc++][ranges] Implement LWG-3865 Sorting a range of pairs
Reviewed By: Mordante, philnik, ldionne, #libc
Differential Revision: https://reviews.llvm.org/D144262
Added:
Modified:
libcxx/docs/Status/Cxx2bIssues.csv
libcxx/include/__utility/pair.h
libcxx/include/utility
libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp
libcxx/test/std/utilities/utility/pairs/pairs.spec/comparison.pass.cpp
libcxx/test/std/utilities/utility/pairs/pairs.spec/three_way_comparison.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/docs/Status/Cxx2bIssues.csv b/libcxx/docs/Status/Cxx2bIssues.csv
index 250508b40278c..53f554f968acd 100644
--- a/libcxx/docs/Status/Cxx2bIssues.csv
+++ b/libcxx/docs/Status/Cxx2bIssues.csv
@@ -294,7 +294,7 @@
"`3843 <https://wg21.link/LWG3843>`__","``std::expected<T,E>::value() &`` assumes ``E`` is copy constructible","February 2023","","",""
"`3847 <https://wg21.link/LWG3847>`__","``ranges::to`` can still return views","February 2023","","","|ranges|"
"`3862 <https://wg21.link/LWG3862>`__","``basic_const_iterator``'s ``common_type`` specialization is underconstrained","February 2023","","",""
-"`3865 <https://wg21.link/LWG3865>`__","Sorting a range of ``pairs``","February 2023","","","|ranges|"
+"`3865 <https://wg21.link/LWG3865>`__","Sorting a range of ``pairs``","February 2023","|Complete|","17.0","|ranges|"
"`3869 <https://wg21.link/LWG3869>`__","Deprecate ``std::errc`` constants related to UNIX STREAMS","February 2023","","",""
"`3870 <https://wg21.link/LWG3870>`__","Remove ``voidify``","February 2023","","",""
"`3871 <https://wg21.link/LWG3871>`__","Adjust note about ``terminate``","February 2023","","",""
diff --git a/libcxx/include/__utility/pair.h b/libcxx/include/__utility/pair.h
index 273c7e248aef8..30797005fc02f 100644
--- a/libcxx/include/__utility/pair.h
+++ b/libcxx/include/__utility/pair.h
@@ -424,22 +424,22 @@ pair(_T1, _T2) -> pair<_T1, _T2>;
// [pairs.spec], specialized algorithms
-template <class _T1, class _T2>
+template <class _T1, class _T2, class _U1, class _U2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
bool
-operator==(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
+operator==(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
{
return __x.first == __y.first && __x.second == __y.second;
}
#if _LIBCPP_STD_VER >= 20
-template <class _T1, class _T2>
+template <class _T1, class _T2, class _U1, class _U2>
_LIBCPP_HIDE_FROM_ABI constexpr
common_comparison_category_t<
- __synth_three_way_result<_T1>,
- __synth_three_way_result<_T2> >
-operator<=>(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
+ __synth_three_way_result<_T1, _U1>,
+ __synth_three_way_result<_T2, _U2> >
+operator<=>(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
{
if (auto __c = std::__synth_three_way(__x.first, __y.first); __c != 0) {
return __c;
@@ -449,42 +449,42 @@ operator<=>(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
#else // _LIBCPP_STD_VER >= 20
-template <class _T1, class _T2>
+template <class _T1, class _T2, class _U1, class _U2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
bool
-operator!=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
+operator!=(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
{
return !(__x == __y);
}
-template <class _T1, class _T2>
+template <class _T1, class _T2, class _U1, class _U2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
bool
-operator< (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
+operator< (const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
{
return __x.first < __y.first || (!(__y.first < __x.first) && __x.second < __y.second);
}
-template <class _T1, class _T2>
+template <class _T1, class _T2, class _U1, class _U2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
bool
-operator> (const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
+operator> (const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
{
return __y < __x;
}
-template <class _T1, class _T2>
+template <class _T1, class _T2, class _U1, class _U2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
bool
-operator>=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
+operator>=(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
{
return !(__x < __y);
}
-template <class _T1, class _T2>
+template <class _T1, class _T2, class _U1, class _U2>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
bool
-operator<=(const pair<_T1,_T2>& __x, const pair<_T1,_T2>& __y)
+operator<=(const pair<_T1,_T2>& __x, const pair<_U1,_U2>& __y)
{
return !(__y < __x);
}
diff --git a/libcxx/include/utility b/libcxx/include/utility
index 845b542132d30..d2f4218549196 100644
--- a/libcxx/include/utility
+++ b/libcxx/include/utility
@@ -117,22 +117,22 @@ struct common_type<pair<T1, T2>, pair<U1, U2>>;
template<class T1, class T2> pair(T1, T2) -> pair<T1, T2>;
-template <class T1, class T2>
-bool operator==(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14
-template <class T1, class T2>
-bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
-template <class T1, class T2>
-bool operator< (const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
-template <class T1, class T2>
-bool operator> (const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
-template <class T1, class T2>
-bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
-template <class T1, class T2>
-bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&); // constexpr in C++14, removed in C++20
-template <class T1, class T2>
- constexpr common_comparison_type_t<synth-three-way-result<T1>,
- synth-three-way-result<T2>>
- operator<=>(const pair<T1,T2>&, const pair<T1,T2>&); // C++20
+template <class T1, class T2, class U1, class U2>
+bool operator==(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14
+template <class T1, class T2, class U1, class U2>
+bool operator!=(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20
+template <class T1, class T2, class U1, class U2>
+bool operator< (const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20
+template <class T1, class T2, class U1, class U2>
+bool operator> (const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20
+template <class T1, class T2, class U1, class U2>
+bool operator>=(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20
+template <class T1, class T2, class U1, class U2>
+bool operator<=(const pair<T1,T2>&, const pair<U1,U2>&); // constexpr in C++14, removed in C++20
+template <class T1, class T2, class U1, class U2>
+ constexpr common_comparison_type_t<synth-three-way-result<T1,U1>,
+ synth-three-way-result<T2,U2>>
+ operator<=>(const pair<T1,T2>&, const pair<U1,U2>&); // C++20
template <class T1, class T2> pair<V1, V2> make_pair(T1&&, T2&&); // constexpr in C++14
template <class T1, class T2>
diff --git a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp
index 957bb67f4f003..5722044360140 100644
--- a/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp
+++ b/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.apply/make_from_tuple.pass.cpp
@@ -61,12 +61,6 @@ constexpr bool do_constexpr_test(Tuple&& tup) {
return std::make_from_tuple<Tp>(std::forward<Tuple>(tup)).args == tup;
}
-// Needed by do_forwarding_test() since it compares pairs of
diff erent types.
-template <class T1, class T2, class U1, class U2>
-inline bool operator==(const std::pair<T1, T2>& lhs, const std::pair<U1, U2>& rhs) {
- return lhs.first == rhs.first && lhs.second == rhs.second;
-}
-
template <class ...ExpectTypes, class Tuple>
bool do_forwarding_test(Tuple&& tup) {
using RawTuple = std::decay_t<Tuple>;
diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.spec/comparison.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.spec/comparison.pass.cpp
index 76c1509fe71ce..76f9771f2b99b 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.spec/comparison.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.spec/comparison.pass.cpp
@@ -10,12 +10,12 @@
// template <class T1, class T2> struct pair
-// template <class T1, class T2> bool operator==(const pair<T1,T2>&, const pair<T1,T2>&);
-// template <class T1, class T2> bool operator!=(const pair<T1,T2>&, const pair<T1,T2>&);
-// template <class T1, class T2> bool operator< (const pair<T1,T2>&, const pair<T1,T2>&);
-// template <class T1, class T2> bool operator> (const pair<T1,T2>&, const pair<T1,T2>&);
-// template <class T1, class T2> bool operator>=(const pair<T1,T2>&, const pair<T1,T2>&);
-// template <class T1, class T2> bool operator<=(const pair<T1,T2>&, const pair<T1,T2>&);
+// template <class T1, class T2, class U1, class U2> bool operator==(const pair<T1,T2>&, const pair<U1,U2>&);
+// template <class T1, class T2, class U1, class U2> bool operator!=(const pair<T1,T2>&, const pair<U1,U2>&);
+// template <class T1, class T2, class U1, class U2> bool operator< (const pair<T1,T2>&, const pair<U1,U2>&);
+// template <class T1, class T2, class U1, class U2> bool operator> (const pair<T1,T2>&, const pair<U1,U2>&);
+// template <class T1, class T2, class U1, class U2> bool operator>=(const pair<T1,T2>&, const pair<U1,U2>&);
+// template <class T1, class T2, class U1, class U2> bool operator<=(const pair<T1,T2>&, const pair<U1,U2>&);
#include <utility>
#include <cassert>
@@ -24,6 +24,18 @@
int main(int, char**)
{
+ {
+ typedef std::pair<int, short> P1;
+ typedef std::pair<long, long> P2;
+ P1 p1(3, static_cast<short>(4));
+ P2 p2(3, 4);
+ assert( (p1 == p2));
+ assert(!(p1 != p2));
+ assert(!(p1 < p2));
+ assert( (p1 <= p2));
+ assert(!(p1 > p2));
+ assert( (p1 >= p2));
+ }
{
typedef std::pair<int, short> P;
P p1(3, static_cast<short>(4));
diff --git a/libcxx/test/std/utilities/utility/pairs/pairs.spec/three_way_comparison.pass.cpp b/libcxx/test/std/utilities/utility/pairs/pairs.spec/three_way_comparison.pass.cpp
index bd93d3f042784..5aa6efb72e9c4 100644
--- a/libcxx/test/std/utilities/utility/pairs/pairs.spec/three_way_comparison.pass.cpp
+++ b/libcxx/test/std/utilities/utility/pairs/pairs.spec/three_way_comparison.pass.cpp
@@ -10,7 +10,9 @@
// template <class T1, class T2> struct pair
-// template <class T1, class T2> bool operator<=>(const pair<T1,T2>&, const pair<T1,T2>&);
+// template <class T1, class T2, class U1, class U2>
+// constexpr common_comparison_category_t<synth-three-way-result<T1, U1>,synth-three-way-result<T2, U2>>
+// operator<=>(const pair<T1,T2>&, const pair<U1,U2>&);
// UNSUPPORTED: c++03, c++11, c++14, c++17
@@ -19,14 +21,37 @@
#include <limits>
#include <type_traits> // std::is_constant_evaluated
#include <utility>
+#include <string>
#include "test_macros.h"
-template<class T> concept HasEqual = requires(T t) { t == t; };
-template<class T> concept HasLess = requires(T t) { t < t; };
-template<class T> concept HasSpaceship = requires(T t) { t <=> t; };
+template <class T>
+concept HasEqual = requires(T t) { t == t; };
+template <class T>
+concept HasLess = requires(T t) { t < t; };
+template <class T, class U = T>
+concept HasSpaceship = requires(T t, U u) { t <=> u; };
constexpr bool test() {
+ {
+ // Pairs of
diff erent types should compare with strong ordering.
+ using P1 = std::pair<int, int>;
+ using P2 = std::pair<long long, long long>;
+ ASSERT_SAME_TYPE(decltype(P1() <=> P2()), std::strong_ordering);
+ assert((P1(1, 1) <=> P2(1, 2)) == std::strong_ordering::less);
+ assert((P1(2, 1) <=> P2(1, 2)) == std::strong_ordering::greater);
+ assert((P1(0, 0) <=> P2(0, 0)) == std::strong_ordering::equal);
+ }
+ {
+ // Pairs of
diff erent types should compare with partial ordering.
+ using P1 = std::pair<int, int>;
+ using P2 = std::pair<double, double>;
+ ASSERT_SAME_TYPE(decltype(P1() <=> P2()), std::partial_ordering);
+ assert((P1(1, 1) <=> P2(1.0, 2.0)) == std::partial_ordering::less);
+ assert((P1(2, 1) <=> P2(1.0, 2.0)) == std::partial_ordering::greater);
+ assert((P1(0, 0) <=> P2(0.0, 0.0)) == std::partial_ordering::equivalent);
+ }
+ { static_assert(!HasSpaceship<std::pair<int, int>, std::pair<std::string, int>>); }
{
// Pairs of types that both have strong ordering should compare with strong ordering.
using P = std::pair<int, int>;
@@ -50,7 +75,7 @@ constexpr bool test() {
}
{
// Pairs of int (strongly ordered) and double (partially ordered) should compare with partial ordering.
- using P = std::pair<int, double>;
+ using P = std::pair<int, double>;
constexpr double nan = std::numeric_limits<double>::quiet_NaN();
ASSERT_SAME_TYPE(decltype(P() <=> P()), std::partial_ordering);
assert((P(1, 1.0) <=> P(1, 2.0)) == std::partial_ordering::less);
@@ -62,7 +87,7 @@ constexpr bool test() {
assert((P(1, nan) <=> P(1, nan)) == std::partial_ordering::unordered);
}
{
- using P = std::pair<double, int>;
+ using P = std::pair<double, int>;
constexpr double nan = std::numeric_limits<double>::quiet_NaN();
ASSERT_SAME_TYPE(decltype(P() <=> P()), std::partial_ordering);
assert((P(2.0, 1) <=> P(1.0, 2)) == std::partial_ordering::greater);
@@ -93,12 +118,12 @@ constexpr bool test() {
#endif
{
{
- using P = std::pair<int, double>;
+ using P = std::pair<int, double>;
constexpr double nan = std::numeric_limits<double>::quiet_NaN();
assert((P(1, 2.0) <=> P(1, nan)) == std::partial_ordering::unordered);
}
{
- using P = std::pair<double, int>;
+ using P = std::pair<double, int>;
constexpr double nan = std::numeric_limits<double>::quiet_NaN();
assert((P(1.0, 1) <=> P(nan, 2)) == std::partial_ordering::unordered);
}
More information about the libcxx-commits
mailing list