[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