libstdc++: Implement LWG 3324 for [cmp.alg] function objects (LWG 3324)
authorJonathan Wakely <jwakely@redhat.com>
Thu, 9 Apr 2020 21:24:57 +0000 (22:24 +0100)
committerJonathan Wakely <jwakely@redhat.com>
Thu, 9 Apr 2020 21:24:57 +0000 (22:24 +0100)
LWG 3324 changed the [cmp.alg] types to use std::compare_three_way
instead of the <=> operator, but we were still using the old
specification. In order to make the existing tests pass the N::X type
needs to be equality comparable, so that three_way_comparable is
satisfied and compare_three_way can be used.

As part of this change I noticed that the compare_three_way call
operator was unconditionally noexcept, which is incorrect.

* libsupc++/compare (compare_three_way): Fix noexcept-specifier.
(strong_order, weak_order, partial_order): Replace uses of <=> with
compare_three_way function object (LWG 3324).
* testsuite/18_support/comparisons/algorithms/partial_order.cc: Add
equality operator so that X satisfies three_way_comparable.
* testsuite/18_support/comparisons/algorithms/strong_order.cc:
Likewise.
* testsuite/18_support/comparisons/algorithms/weak_order.cc: Likewise.

libstdc++-v3/ChangeLog
libstdc++-v3/libsupc++/compare
libstdc++-v3/testsuite/18_support/comparisons/algorithms/partial_order.cc
libstdc++-v3/testsuite/18_support/comparisons/algorithms/strong_order.cc
libstdc++-v3/testsuite/18_support/comparisons/algorithms/weak_order.cc

index 98812f0faae5b874c1a680ff2e9a85b5638fe46e..3ca7a0e7165fc233f1e62ffb7f5d4d6a11797a20 100644 (file)
@@ -1,5 +1,14 @@
 2020-04-09  Jonathan Wakely  <jwakely@redhat.com>
 
+       * libsupc++/compare (compare_three_way): Fix noexcept-specifier.
+       (strong_order, weak_order, partial_order): Replace uses of <=> with
+       compare_three_way function object (LWG 3324).
+       * testsuite/18_support/comparisons/algorithms/partial_order.cc: Add
+       equality operator so that X satisfies three_way_comparable.
+       * testsuite/18_support/comparisons/algorithms/strong_order.cc:
+       Likewise.
+       * testsuite/18_support/comparisons/algorithms/weak_order.cc: Likewise.
+
        * include/bits/unique_ptr.h (operator<=>): Define for C++20.
        * testsuite/20_util/default_delete/48631_neg.cc: Adjust dg-error line.
        * testsuite/20_util/default_delete/void_neg.cc: Likewise.
index b88b691b9e11b93adaf32b11482c58c6ad2d93ee..37601d32648886c29293ce7bee3370c7081d753a 100644 (file)
@@ -419,7 +419,8 @@ namespace std
       = __detail::__weakly_eq_cmp_with<_Tp, _Tp>
       && __detail::__partially_ordered_with<_Tp, _Tp>
       && requires(const remove_reference_t<_Tp>& __a,
-                 const remove_reference_t<_Tp>& __b) {
+                 const remove_reference_t<_Tp>& __b)
+      {
        { __a <=> __b } -> __detail::__compares_as<_Cat>;
       };
 
@@ -435,7 +436,8 @@ namespace std
       && __detail::__weakly_eq_cmp_with<_Tp, _Up>
       && __detail::__partially_ordered_with<_Tp, _Up>
       && requires(const remove_reference_t<_Tp>& __t,
-                 const remove_reference_t<_Up>& __u) {
+                 const remove_reference_t<_Up>& __u)
+      {
        { __t <=> __u } -> __detail::__compares_as<_Cat>;
        { __u <=> __t } -> __detail::__compares_as<_Cat>;
       };
@@ -494,7 +496,8 @@ namespace std
     template<typename _Tp, typename _Up>
       requires three_way_comparable_with<_Tp, _Up>
       constexpr auto
-      operator()(_Tp&& __t, _Up&& __u) const noexcept
+      operator()(_Tp&& __t, _Up&& __u) const
+      noexcept(noexcept(std::declval<_Tp>() <=> std::declval<_Up>()))
       {
        if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>)
          {
@@ -579,16 +582,16 @@ namespace std
        };
 
     template<typename _Ord, typename _Tp, typename _Up>
-      concept __op_cmp = requires(_Tp&& __t, _Up&& __u)
+      concept __cmp3way = requires(_Tp&& __t, _Up&& __u, compare_three_way __c)
        {
-         _Ord(static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u));
+         _Ord(__c(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)));
        };
 
     template<typename _Tp, typename _Up>
       concept __strongly_ordered
        = __adl_strong<_Tp, _Up>
          // FIXME: || floating_point<remove_reference_t<_Tp>>
-         || __op_cmp<strong_ordering, _Tp, _Up>;
+         || __cmp3way<strong_ordering, _Tp, _Up>;
 
     class _Strong_order
     {
@@ -601,8 +604,9 @@ namespace std
          else if constexpr (__adl_strong<_Tp, _Up>)
            return noexcept(strong_ordering(strong_order(std::declval<_Tp>(),
                                                         std::declval<_Up>())));
-         else if constexpr (__op_cmp<strong_ordering, _Tp, _Up>)
-           return noexcept(std::declval<_Tp>() <=> std::declval<_Up>());
+         else if constexpr (__cmp3way<strong_ordering, _Tp, _Up>)
+           return noexcept(compare_three_way()(std::declval<_Tp>(),
+                                               std::declval<_Up>()));
        }
 
       friend class _Weak_order;
@@ -623,8 +627,9 @@ namespace std
          else */ if constexpr (__adl_strong<_Tp, _Up>)
            return strong_ordering(strong_order(static_cast<_Tp&&>(__e),
                                                static_cast<_Up&&>(__f)));
-         else if constexpr (__op_cmp<strong_ordering, _Tp, _Up>)
-           return static_cast<_Tp&&>(__e) <=> static_cast<_Up&&>(__f);
+         else if constexpr (__cmp3way<strong_ordering, _Tp, _Up>)
+           return compare_three_way()(static_cast<_Tp&&>(__e),
+                                      static_cast<_Up&&>(__f));
        }
     };
 
@@ -632,7 +637,7 @@ namespace std
       concept __weakly_ordered
        = floating_point<remove_reference_t<_Tp>>
          || __adl_weak<_Tp, _Up>
-         || __op_cmp<weak_ordering, _Tp, _Up>
+         || __cmp3way<weak_ordering, _Tp, _Up>
          || __strongly_ordered<_Tp, _Up>;
 
     class _Weak_order
@@ -646,8 +651,9 @@ namespace std
          else if constexpr (__adl_weak<_Tp, _Up>)
            return noexcept(weak_ordering(weak_order(std::declval<_Tp>(),
                                                     std::declval<_Up>())));
-         else if constexpr (__op_cmp<weak_ordering, _Tp, _Up>)
-           return noexcept(std::declval<_Tp>() <=> std::declval<_Up>());
+         else if constexpr (__cmp3way<weak_ordering, _Tp, _Up>)
+           return noexcept(compare_three_way()(std::declval<_Tp>(),
+                                               std::declval<_Up>()));
          else if constexpr (__strongly_ordered<_Tp, _Up>)
            return _Strong_order::_S_noexcept<_Tp, _Up>();
        }
@@ -669,8 +675,9 @@ namespace std
          else if constexpr (__adl_weak<_Tp, _Up>)
            return weak_ordering(weak_order(static_cast<_Tp&&>(__e),
                                            static_cast<_Up&&>(__f)));
-         else if constexpr (__op_cmp<weak_ordering, _Tp, _Up>)
-           return static_cast<_Tp&&>(__e) <=> static_cast<_Up&&>(__f);
+         else if constexpr (__cmp3way<weak_ordering, _Tp, _Up>)
+           return compare_three_way()(static_cast<_Tp&&>(__e),
+                                      static_cast<_Up&&>(__f));
          else if constexpr (__strongly_ordered<_Tp, _Up>)
            return _Strong_order{}(static_cast<_Tp&&>(__e),
                                   static_cast<_Up&&>(__f));
@@ -680,7 +687,7 @@ namespace std
     template<typename _Tp, typename _Up>
       concept __partially_ordered
        = __adl_partial<_Tp, _Up>
-       || __op_cmp<partial_ordering, _Tp, _Up>
+       || __cmp3way<partial_ordering, _Tp, _Up>
        || __weakly_ordered<_Tp, _Up>;
 
     class _Partial_order
@@ -692,8 +699,9 @@ namespace std
          if constexpr (__adl_partial<_Tp, _Up>)
            return noexcept(partial_ordering(partial_order(std::declval<_Tp>(),
                                                         std::declval<_Up>())));
-         else if constexpr (__op_cmp<partial_ordering, _Tp, _Up>)
-           return noexcept(std::declval<_Tp>() <=> std::declval<_Up>());
+         else if constexpr (__cmp3way<partial_ordering, _Tp, _Up>)
+           return noexcept(compare_three_way()(std::declval<_Tp>(),
+                                               std::declval<_Up>()));
          else if constexpr (__weakly_ordered<_Tp, _Up>)
            return _Weak_order::_S_noexcept<_Tp, _Up>();
        }
@@ -712,8 +720,9 @@ namespace std
          if constexpr (__adl_partial<_Tp, _Up>)
            return partial_ordering(partial_order(static_cast<_Tp&&>(__e),
                                                  static_cast<_Up&&>(__f)));
-         else if constexpr (__op_cmp<partial_ordering, _Tp, _Up>)
-           return static_cast<_Tp&&>(__e) <=> static_cast<_Up&&>(__f);
+         else if constexpr (__cmp3way<partial_ordering, _Tp, _Up>)
+           return compare_three_way()(static_cast<_Tp&&>(__e),
+                                      static_cast<_Up&&>(__f));
          else if constexpr (__weakly_ordered<_Tp, _Up>)
            return _Weak_order{}(static_cast<_Tp&&>(__e),
                                 static_cast<_Up&&>(__f));
index aef738d538a9dbee32e6b86e9f42812e12b387d6..0806eabf74a13073baa24cd1c6245d5b25f86cc1 100644 (file)
@@ -94,6 +94,10 @@ namespace N
       return partial_ordering::equivalent;
     return r.i <=> l.i;
   }
+
+  constexpr bool operator==(X l, X r) { return std::is_eq(l <=> r); }
+
+  static_assert(std::three_way_comparable<X>);
 }
 
 void
index fd0a10c1f56b7317a0aa19e0c36590a28b08f755..edbcc9f1acbdec97697c4b0d5c5ed0c48da39d56 100644 (file)
@@ -47,6 +47,10 @@ namespace N
       return strong_ordering::equivalent;
     return r.i <=> l.i;
   }
+
+  constexpr bool operator==(X l, X r) { return std::is_eq(l <=> r); }
+
+  static_assert(std::three_way_comparable<X>);
 }
 using N::X;
 
index a5405dbc377416db3add7faf0a298882acbd9c33..d7d43ade8d2622b1ea841a6b15ff94ef55afe0e3 100644 (file)
@@ -95,6 +95,10 @@ namespace N
       return weak_ordering::equivalent;
     return r.i <=> l.i;
   }
+
+  constexpr bool operator==(X l, X r) { return std::is_eq(l <=> r); }
+
+  static_assert(std::three_way_comparable<X>);
 }
 
 void