[libcxx-commits] [libcxx] 879cbac - [libc++][ranges] Add range.cmp: equal_to, not_equal_to, less, etc.

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Apr 22 18:06:56 PDT 2021


Author: zoecarver
Date: 2021-04-22T17:33:04-07:00
New Revision: 879cbac08ba17566ad61ff2b9d7180bcab4a0d1e

URL: https://github.com/llvm/llvm-project/commit/879cbac08ba17566ad61ff2b9d7180bcab4a0d1e
DIFF: https://github.com/llvm/llvm-project/commit/879cbac08ba17566ad61ff2b9d7180bcab4a0d1e.diff

LOG: [libc++][ranges] Add range.cmp: equal_to, not_equal_to, less, etc.

Adds the six new concept constrained comparisons.

Differential Revision: https://reviews.llvm.org/D100429

Added: 
    libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
    libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
    libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
    libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
    libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
    libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
    libcxx/test/support/compare_types.h
    libcxx/test/support/pointer_comparison_test_helper.h

Modified: 
    libcxx/include/functional
    libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable.compile.pass.cpp
    libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
    libcxx/test/std/concepts/concepts.compare/concepts.totallyordered/totally_ordered.pass.cpp
    libcxx/test/std/concepts/concepts.compare/concepts.totallyordered/totally_ordered_with.pass.cpp
    libcxx/test/std/utilities/function.objects/comparisons/greater.pass.cpp
    libcxx/test/std/utilities/function.objects/comparisons/greater_equal.pass.cpp
    libcxx/test/std/utilities/function.objects/comparisons/less.pass.cpp
    libcxx/test/std/utilities/function.objects/comparisons/less_equal.pass.cpp

Removed: 
    libcxx/test/std/concepts/concepts.compare/types.h
    libcxx/test/std/utilities/function.objects/comparisons/pointer_comparison_test_helper.h


################################################################################
diff  --git a/libcxx/include/functional b/libcxx/include/functional
index 62e9373ad14d0..19d74a3ec6bb8 100644
--- a/libcxx/include/functional
+++ b/libcxx/include/functional
@@ -507,6 +507,7 @@ POLICY:  For non-variadic implementations, the number of arguments is limited
 */
 
 #include <__config>
+#include <concepts>
 #include <type_traits>
 #include <typeinfo>
 #include <exception>
@@ -3222,6 +3223,80 @@ struct identity {
 };
 #endif // _LIBCPP_STD_VER > 17
 
+#if !defined(_LIBCPP_HAS_NO_RANGES)
+
+namespace ranges {
+
+struct equal_to {
+  template <class _Tp, class _Up>
+  requires equality_comparable_with<_Tp, _Up>
+  [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const
+      noexcept(noexcept(bool(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u)))) {
+    return _VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u);
+  }
+
+  using is_transparent = void;
+};
+
+struct not_equal_to {
+  template <class _Tp, class _Up>
+  requires equality_comparable_with<_Tp, _Up>
+  [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const
+      noexcept(noexcept(bool(!(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u))))) {
+    return !(_VSTD::forward<_Tp>(__t) == _VSTD::forward<_Up>(__u));
+  }
+
+  using is_transparent = void;
+};
+
+struct greater {
+  template <class _Tp, class _Up>
+  requires totally_ordered_with<_Tp, _Up>
+  [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const
+      noexcept(noexcept(bool(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t)))) {
+    return _VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t);
+  }
+
+  using is_transparent = void;
+};
+
+struct less {
+  template <class _Tp, class _Up>
+  requires totally_ordered_with<_Tp, _Up>
+  [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const
+      noexcept(noexcept(bool(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u)))) {
+    return _VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u);
+  }
+
+  using is_transparent = void;
+};
+
+struct greater_equal {
+  template <class _Tp, class _Up>
+  requires totally_ordered_with<_Tp, _Up>
+  [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const
+      noexcept(noexcept(bool(!(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u))))) {
+    return !(_VSTD::forward<_Tp>(__t) < _VSTD::forward<_Up>(__u));
+  }
+
+  using is_transparent = void;
+};
+
+struct less_equal {
+  template <class _Tp, class _Up>
+  requires totally_ordered_with<_Tp, _Up>
+  [[nodiscard]] constexpr bool operator()(_Tp &&__t, _Up &&__u) const
+      noexcept(noexcept(bool(!(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t))))) {
+    return !(_VSTD::forward<_Up>(__u) < _VSTD::forward<_Tp>(__t));
+  }
+
+  using is_transparent = void;
+};
+
+} // namespace ranges
+
+#endif // !defined(_LIBCPP_HAS_NO_RANGES)
+
 _LIBCPP_END_NAMESPACE_STD
 
 #endif // _LIBCPP_FUNCTIONAL

diff  --git a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable.compile.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable.compile.pass.cpp
index 0211ee3d531ec..5290e06dc8280 100644
--- a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable.compile.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable.compile.pass.cpp
@@ -27,7 +27,7 @@
 #include <unordered_set>
 #include <vector>
 
-#include "../types.h"
+#include "compare_types.h"
 
 namespace fundamentals {
 static_assert(std::equality_comparable<int>);

diff  --git a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
index a65e47f936da8..a9caf8dc6e9bf 100644
--- a/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.compare/concept.equalitycomparable/equality_comparable_with.compile.pass.cpp
@@ -27,7 +27,7 @@
 #include <unordered_set>
 #include <vector>
 
-#include "../types.h"
+#include "compare_types.h"
 
 template <class T, class U>
 constexpr bool check_equality_comparable_with() {

diff  --git a/libcxx/test/std/concepts/concepts.compare/concepts.totallyordered/totally_ordered.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concepts.totallyordered/totally_ordered.pass.cpp
index fce1efc0cd5d3..03d82ec97557e 100644
--- a/libcxx/test/std/concepts/concepts.compare/concepts.totallyordered/totally_ordered.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.compare/concepts.totallyordered/totally_ordered.pass.cpp
@@ -26,7 +26,7 @@
 #include <unordered_set>
 #include <vector>
 
-#include "../types.h"
+#include "compare_types.h"
 #include "test_macros.h"
 
 // `models_totally_ordered` checks that `std::totally_ordered` subsumes

diff  --git a/libcxx/test/std/concepts/concepts.compare/concepts.totallyordered/totally_ordered_with.pass.cpp b/libcxx/test/std/concepts/concepts.compare/concepts.totallyordered/totally_ordered_with.pass.cpp
index 345abac552fed..199f022f58836 100644
--- a/libcxx/test/std/concepts/concepts.compare/concepts.totallyordered/totally_ordered_with.pass.cpp
+++ b/libcxx/test/std/concepts/concepts.compare/concepts.totallyordered/totally_ordered_with.pass.cpp
@@ -26,7 +26,7 @@
 #include <unordered_set>
 #include <vector>
 
-#include "../types.h"
+#include "compare_types.h"
 #include "test_macros.h"
 
 template <class T, class U>

diff  --git a/libcxx/test/std/utilities/function.objects/comparisons/greater.pass.cpp b/libcxx/test/std/utilities/function.objects/comparisons/greater.pass.cpp
index b1f1fe65667f8..1f79d2351327d 100644
--- a/libcxx/test/std/utilities/function.objects/comparisons/greater.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/comparisons/greater.pass.cpp
@@ -30,7 +30,7 @@ int main(int, char**)
     {
         // test total ordering of int* for greater<int*> and
         // greater<void>.
-        do_pointer_comparison_test<int, std::greater>();
+        do_pointer_comparison_test<std::greater>();
     }
 #if TEST_STD_VER > 11
     typedef std::greater<> F2;

diff  --git a/libcxx/test/std/utilities/function.objects/comparisons/greater_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/comparisons/greater_equal.pass.cpp
index 30cf7e0bca115..f259b5d27ddb8 100644
--- a/libcxx/test/std/utilities/function.objects/comparisons/greater_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/comparisons/greater_equal.pass.cpp
@@ -30,7 +30,7 @@ int main(int, char**)
     {
         // test total ordering of int* for greater_equal<int*> and
         // greater_equal<void>.
-        do_pointer_comparison_test<int, std::greater_equal>();
+        do_pointer_comparison_test<std::greater_equal>();
     }
 #if TEST_STD_VER > 11
     typedef std::greater_equal<> F2;

diff  --git a/libcxx/test/std/utilities/function.objects/comparisons/less.pass.cpp b/libcxx/test/std/utilities/function.objects/comparisons/less.pass.cpp
index 88b7c784ea7e1..c5da63c1f41ea 100644
--- a/libcxx/test/std/utilities/function.objects/comparisons/less.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/comparisons/less.pass.cpp
@@ -29,7 +29,7 @@ int main(int, char**)
     assert(f(6, 36));
     {
         // test total ordering of int* for less<int*> and less<void>.
-        do_pointer_comparison_test<int, std::less>();
+        do_pointer_comparison_test<std::less>();
     }
 #if TEST_STD_VER > 11
     typedef std::less<> F2;

diff  --git a/libcxx/test/std/utilities/function.objects/comparisons/less_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/comparisons/less_equal.pass.cpp
index 5aa6d799577a3..fe91f2728fd88 100644
--- a/libcxx/test/std/utilities/function.objects/comparisons/less_equal.pass.cpp
+++ b/libcxx/test/std/utilities/function.objects/comparisons/less_equal.pass.cpp
@@ -30,7 +30,7 @@ int main(int, char**)
     {
         // test total ordering of int* for less_equal<int*> and
         // less_equal<void>.
-        do_pointer_comparison_test<int, std::less_equal>();
+        do_pointer_comparison_test<std::less_equal>();
     }
 #if TEST_STD_VER > 11
     typedef std::less_equal<> F2;

diff  --git a/libcxx/test/std/utilities/function.objects/comparisons/pointer_comparison_test_helper.h b/libcxx/test/std/utilities/function.objects/comparisons/pointer_comparison_test_helper.h
deleted file mode 100644
index ac4df550a3364..0000000000000
--- a/libcxx/test/std/utilities/function.objects/comparisons/pointer_comparison_test_helper.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef POINTER_COMPARISON_TEST_HELPER_H
-#define POINTER_COMPARISON_TEST_HELPER_H
-
-#include <vector>
-#include <memory>
-#include <cstdint>
-#include <cassert>
-
-#include "test_macros.h"
-
-template <class T, template<class> class CompareTemplate>
-void do_pointer_comparison_test() {
-    typedef CompareTemplate<T*> Compare;
-    typedef CompareTemplate<std::uintptr_t> UIntCompare;
-#if TEST_STD_VER > 11
-    typedef CompareTemplate<void> VoidCompare;
-#else
-    typedef Compare VoidCompare;
-#endif
-    std::vector<std::shared_ptr<T> > pointers;
-    const std::size_t test_size = 100;
-    for (size_t i=0; i < test_size; ++i)
-        pointers.push_back(std::shared_ptr<T>(new T()));
-    Compare comp;
-    UIntCompare ucomp;
-    VoidCompare vcomp;
-    for (size_t i=0; i < test_size; ++i) {
-        for (size_t j=0; j < test_size; ++j) {
-            T* lhs = pointers[i].get();
-            T* rhs = pointers[j].get();
-            std::uintptr_t lhs_uint = reinterpret_cast<std::uintptr_t>(lhs);
-            std::uintptr_t rhs_uint = reinterpret_cast<std::uintptr_t>(rhs);
-            assert(comp(lhs, rhs) == ucomp(lhs_uint, rhs_uint));
-            assert(vcomp(lhs, rhs) == ucomp(lhs_uint, rhs_uint));
-        }
-    }
-}
-
-#endif // POINTER_COMPARISON_TEST_HELPER_H

diff  --git a/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
new file mode 100644
index 0000000000000..c27159407bb5f
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/equal_to.pass.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// <functional>
+
+// ranges::equal_to
+
+#include <functional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "compare_types.h"
+#include "MoveOnly.h"
+#include "pointer_comparison_test_helper.h"
+
+struct NotEqualityComparable {
+  friend bool operator==(const NotEqualityComparable&, const NotEqualityComparable&);
+  friend bool operator!=(const NotEqualityComparable&, const NotEqualityComparable&) = delete;
+};
+
+static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
+static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
+
+static_assert(requires { typename std::ranges::equal_to::is_transparent; });
+
+constexpr bool test() {
+  auto fn = std::ranges::equal_to();
+
+  assert(fn(MoveOnly(42), MoveOnly(42)));
+
+  ForwardingTestObject a;
+  ForwardingTestObject b;
+  assert(!fn(a, b));
+  assert(fn(std::move(a), std::move(b)));
+
+  assert(!fn(1, 2));
+  assert(!fn(2, 1));
+  assert(fn(2, 2));
+
+  assert(!fn(2, 1L));
+
+  return true;
+}
+
+int main(int, char**) {
+
+  test();
+  static_assert(test());
+
+  // test total ordering of int* for equal_to<int*> and equal_to<void>.
+  do_pointer_comparison_test(std::ranges::equal_to());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
new file mode 100644
index 0000000000000..95f490d951023
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater.pass.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// <functional>
+
+// ranges::greater
+
+#include <functional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "compare_types.h"
+#include "MoveOnly.h"
+#include "pointer_comparison_test_helper.h"
+
+struct NotTotallyOrdered {
+  friend bool operator<(const NotTotallyOrdered&, const NotTotallyOrdered&);
+};
+
+static_assert(!std::is_invocable_v<std::ranges::greater, NotTotallyOrdered, NotTotallyOrdered>);
+static_assert(!std::is_invocable_v<std::ranges::greater, int, MoveOnly>);
+static_assert(std::is_invocable_v<std::ranges::greater, explicit_operators, explicit_operators>);
+
+static_assert(requires { typename std::ranges::greater::is_transparent; });
+
+constexpr bool test() {
+  auto fn = std::ranges::greater();
+
+  assert(fn(MoveOnly(42), MoveOnly(41)));
+
+  ForwardingTestObject a;
+  ForwardingTestObject b;
+  assert(!fn(a, b));
+  assert(fn(std::move(a), std::move(b)));
+
+  assert(!fn(2, 2));
+  assert(!fn(1, 2));
+  assert(fn(2, 1));
+
+  assert(fn(2, 1L));
+
+  return true;
+}
+
+int main(int, char**) {
+
+  test();
+  static_assert(test());
+
+  // test total ordering of int* for greater<int*> and greater<void>.
+  do_pointer_comparison_test(std::ranges::greater());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
new file mode 100644
index 0000000000000..a3e8ff215bb75
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/greater_equal.pass.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// <functional>
+
+// ranges::greater_equal
+
+#include <functional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "compare_types.h"
+#include "MoveOnly.h"
+#include "pointer_comparison_test_helper.h"
+
+struct NotTotallyOrdered {
+  friend bool operator<(const NotTotallyOrdered&, const NotTotallyOrdered&);
+};
+
+static_assert(!std::is_invocable_v<std::ranges::greater_equal, NotTotallyOrdered, NotTotallyOrdered>);
+static_assert(!std::is_invocable_v<std::ranges::greater_equal, int, MoveOnly>);
+static_assert(std::is_invocable_v<std::ranges::greater_equal, explicit_operators, explicit_operators>);
+
+static_assert(requires { typename std::ranges::greater_equal::is_transparent; });
+
+constexpr bool test() {
+  auto fn = std::ranges::greater_equal();
+
+  assert(fn(MoveOnly(42), MoveOnly(42)));
+
+  ForwardingTestObject a;
+  ForwardingTestObject b;
+  assert(fn(a, b));
+  assert(!fn(std::move(a), std::move(b)));
+
+  assert(fn(2, 2));
+  assert(fn(2, 1));
+  assert(!fn(1, 2));
+
+  assert(fn(2, 1L));
+
+  return true;
+}
+
+int main(int, char**) {
+
+  test();
+  static_assert(test());
+
+  // test total ordering of int* for greater_equal<int*> and greater_equal<void>.
+  do_pointer_comparison_test(std::ranges::greater_equal());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
new file mode 100644
index 0000000000000..72f54b7b923fb
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less.pass.cpp
@@ -0,0 +1,63 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// <functional>
+
+// ranges::less
+
+#include <functional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "compare_types.h"
+#include "MoveOnly.h"
+#include "pointer_comparison_test_helper.h"
+
+struct NotTotallyOrdered {
+  friend bool operator<(const NotTotallyOrdered&, const NotTotallyOrdered&);
+};
+
+static_assert(!std::is_invocable_v<std::ranges::less, NotTotallyOrdered, NotTotallyOrdered>);
+static_assert(!std::is_invocable_v<std::ranges::less, int, MoveOnly>);
+static_assert(std::is_invocable_v<std::ranges::less, explicit_operators, explicit_operators>);
+
+static_assert(requires { typename std::ranges::less::is_transparent; });
+
+constexpr bool test() {
+  auto fn = std::ranges::less();
+
+  assert(fn(MoveOnly(41), MoveOnly(42)));
+
+  ForwardingTestObject a;
+  ForwardingTestObject b;
+  assert(!fn(a, b));
+  assert(fn(std::move(a), std::move(b)));
+
+  assert(fn(1, 2));
+  assert(!fn(2, 2));
+  assert(!fn(2, 1));
+
+  assert(!fn(2, 1L));
+
+  return true;
+}
+
+int main(int, char**) {
+
+  test();
+  static_assert(test());
+
+  // test total ordering of int* for less<int*> and less<void>.
+  do_pointer_comparison_test(std::ranges::less());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
new file mode 100644
index 0000000000000..05cc56e89d403
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/less_equal.pass.cpp
@@ -0,0 +1,64 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// <functional>
+
+// ranges::less_equal
+
+#include <functional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "compare_types.h"
+#include "MoveOnly.h"
+#include "pointer_comparison_test_helper.h"
+
+struct NotTotallyOrdered {
+  friend bool operator<(const NotTotallyOrdered&, const NotTotallyOrdered&);
+};
+
+static_assert(!std::is_invocable_v<std::ranges::less_equal, NotTotallyOrdered, NotTotallyOrdered>);
+static_assert(!std::is_invocable_v<std::ranges::less_equal, int, MoveOnly>);
+static_assert(std::is_invocable_v<std::ranges::less_equal, explicit_operators, explicit_operators>);
+
+static_assert(requires { typename std::ranges::less_equal::is_transparent; });
+
+constexpr bool test() {
+  auto fn = std::ranges::less_equal();
+
+  assert(fn(MoveOnly(41), MoveOnly(42)));
+
+  // These are the opposite of other tests.
+  ForwardingTestObject a;
+  ForwardingTestObject b;
+  assert(fn(a, b));
+  assert(!fn(std::move(a), std::move(b)));
+
+  assert(fn(1, 2));
+  assert(fn(2, 2));
+  assert(!fn(2, 1));
+
+  assert(!fn(2, 1L));
+
+  return true;
+}
+
+int main(int, char**) {
+
+  test();
+  static_assert(test());
+
+  // test total ordering of int* for less_equal<int*> and less_equal<void>.
+  do_pointer_comparison_test(std::ranges::less_equal());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
new file mode 100644
index 0000000000000..142aaf1f74286
--- /dev/null
+++ b/libcxx/test/std/utilities/function.objects/range.cmp/not_equal_to.pass.cpp
@@ -0,0 +1,75 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+
+// <functional>
+
+// ranges::not_equal_to
+
+#include <functional>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+#include "compare_types.h"
+#include "MoveOnly.h"
+#include "pointer_comparison_test_helper.h"
+
+struct NotEqualityComparable {
+  friend bool operator==(const NotEqualityComparable&, const NotEqualityComparable&);
+  friend bool operator!=(const NotEqualityComparable&, const NotEqualityComparable&) = delete;
+};
+
+static_assert(!std::is_invocable_v<std::ranges::equal_to, NotEqualityComparable, NotEqualityComparable>);
+static_assert(!std::is_invocable_v<std::ranges::equal_to, int, MoveOnly>);
+static_assert(std::is_invocable_v<std::ranges::equal_to, explicit_operators, explicit_operators>);
+
+static_assert(requires { typename std::ranges::not_equal_to::is_transparent; });
+
+struct PtrAndNotEqOperator {
+  constexpr operator void*() const { return nullptr; }
+  // We *don't* want operator!= to be picked here.
+  friend constexpr bool operator!=(PtrAndNotEqOperator, PtrAndNotEqOperator) { return true; }
+};
+
+constexpr bool test() {
+  auto fn = std::ranges::not_equal_to();
+
+  assert(fn(MoveOnly(41), MoveOnly(42)));
+
+  // These are the opposite of other tests.
+  ForwardingTestObject a;
+  ForwardingTestObject b;
+  assert(fn(a, b));
+  assert(!fn(std::move(a), std::move(b)));
+
+  assert(fn(1, 2));
+  assert(!fn(2, 2));
+  assert(fn(2, 1));
+
+  assert(fn(2, 1L));
+
+  // Make sure that "ranges::equal_to(x, y) == !ranges::not_equal_to(x, y)", even here.
+  assert(!fn(PtrAndNotEqOperator(), PtrAndNotEqOperator()));
+  assert(std::ranges::equal_to()(PtrAndNotEqOperator(), PtrAndNotEqOperator()));
+
+  return true;
+}
+
+int main(int, char**) {
+
+  test();
+  static_assert(test());
+
+  // test total ordering of int* for not_equal_to<int*> and not_equal_to<void>.
+  do_pointer_comparison_test(std::ranges::not_equal_to());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/concepts/concepts.compare/types.h b/libcxx/test/support/compare_types.h
similarity index 73%
rename from libcxx/test/std/concepts/concepts.compare/types.h
rename to libcxx/test/support/compare_types.h
index de816a371e45e..1d448da5407e1 100644
--- a/libcxx/test/std/concepts/concepts.compare/types.h
+++ b/libcxx/test/support/compare_types.h
@@ -5,8 +5,8 @@
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 //
 //===----------------------------------------------------------------------===//
-#ifndef TEST_STD_CONCEPTS_COMPARISON_TYPES_H
-#define TEST_STD_CONCEPTS_COMPARISON_TYPES_H
+#ifndef TEST_SUPPORT_COMPARE_TYPES_H
+#define TEST_SUPPORT_COMPARE_TYPES_H
 
 #include <compare>
 #include <concepts>
@@ -23,8 +23,7 @@ struct cxx20_member_eq {
 };
 
 struct cxx20_friend_eq {
-  friend bool operator==(cxx20_friend_eq const&,
-                         cxx20_friend_eq const&) = default;
+  friend bool operator==(cxx20_friend_eq const&, cxx20_friend_eq const&) = default;
 };
 
 struct member_three_way_comparable {
@@ -32,8 +31,7 @@ struct member_three_way_comparable {
 };
 
 struct friend_three_way_comparable {
-  friend auto operator<=>(friend_three_way_comparable const&,
-                          friend_three_way_comparable const&) = default;
+  friend auto operator<=>(friend_three_way_comparable const&, friend_three_way_comparable const&) = default;
 };
 
 struct explicit_operators {
@@ -43,16 +41,11 @@ struct explicit_operators {
   friend bool operator>(explicit_operators, explicit_operators) noexcept;
   friend bool operator<=(explicit_operators, explicit_operators) noexcept;
   friend bool operator>=(explicit_operators, explicit_operators) noexcept;
-  friend bool operator<=>(explicit_operators, explicit_operators) noexcept;
 
-  friend bool operator==(explicit_operators const&,
-                         equality_comparable_with_ec1 const&) noexcept;
-  friend bool operator==(equality_comparable_with_ec1 const&,
-                         explicit_operators const&) noexcept;
-  friend bool operator!=(explicit_operators const&,
-                         equality_comparable_with_ec1 const&) noexcept;
-  friend bool operator!=(equality_comparable_with_ec1 const&,
-                         explicit_operators const&) noexcept;
+  friend bool operator==(explicit_operators const&, equality_comparable_with_ec1 const&) noexcept;
+  friend bool operator==(equality_comparable_with_ec1 const&, explicit_operators const&) noexcept;
+  friend bool operator!=(explicit_operators const&, equality_comparable_with_ec1 const&) noexcept;
+  friend bool operator!=(equality_comparable_with_ec1 const&, explicit_operators const&) noexcept;
 };
 
 struct 
diff erent_return_types {
@@ -76,8 +69,7 @@ struct boolean {
 };
 
 struct one_member_one_friend {
-  friend boolean operator==(one_member_one_friend,
-                            one_member_one_friend) noexcept;
+  friend boolean operator==(one_member_one_friend, one_member_one_friend) noexcept;
   boolean operator!=(one_member_one_friend) const noexcept;
 
   operator explicit_operators() const noexcept;
@@ -208,51 +200,39 @@ struct wrong_return_type {
 };
 
 struct cxx20_member_eq_operator_with_deleted_ne {
-  bool
-  operator==(cxx20_member_eq_operator_with_deleted_ne const&) const = default;
-  bool
-  operator!=(cxx20_member_eq_operator_with_deleted_ne const&) const = delete;
+  bool operator==(cxx20_member_eq_operator_with_deleted_ne const&) const = default;
+  bool operator!=(cxx20_member_eq_operator_with_deleted_ne const&) const = delete;
 };
 
 struct cxx20_friend_eq_operator_with_deleted_ne {
-  friend bool
-  operator==(cxx20_friend_eq_operator_with_deleted_ne const&,
-             cxx20_friend_eq_operator_with_deleted_ne const&) = default;
-  friend bool
-  operator!=(cxx20_friend_eq_operator_with_deleted_ne const&,
-             cxx20_friend_eq_operator_with_deleted_ne const&) = delete;
+  friend bool operator==(cxx20_friend_eq_operator_with_deleted_ne const&,
+                         cxx20_friend_eq_operator_with_deleted_ne const&) = default;
+  friend bool operator!=(cxx20_friend_eq_operator_with_deleted_ne const&,
+                         cxx20_friend_eq_operator_with_deleted_ne const&) = delete;
 };
 
 struct member_three_way_comparable_with_deleted_eq {
-  auto operator<=>(member_three_way_comparable_with_deleted_eq const&) const =
-      default;
-  bool
-  operator==(member_three_way_comparable_with_deleted_eq const&) const = delete;
+  auto operator<=>(member_three_way_comparable_with_deleted_eq const&) const = default;
+  bool operator==(member_three_way_comparable_with_deleted_eq const&) const = delete;
 };
 
 struct member_three_way_comparable_with_deleted_ne {
-  auto operator<=>(member_three_way_comparable_with_deleted_ne const&) const =
-      default;
-  bool
-  operator!=(member_three_way_comparable_with_deleted_ne const&) const = delete;
+  auto operator<=>(member_three_way_comparable_with_deleted_ne const&) const = default;
+  bool operator!=(member_three_way_comparable_with_deleted_ne const&) const = delete;
 };
 
 struct friend_three_way_comparable_with_deleted_eq {
-  friend auto
-  operator<=>(friend_three_way_comparable_with_deleted_eq const&,
-              friend_three_way_comparable_with_deleted_eq const&) = default;
-  friend bool
-  operator==(friend_three_way_comparable_with_deleted_eq const&,
-             friend_three_way_comparable_with_deleted_eq const&) = delete;
+  friend auto operator<=>(friend_three_way_comparable_with_deleted_eq const&,
+                          friend_three_way_comparable_with_deleted_eq const&) = default;
+  friend bool operator==(friend_three_way_comparable_with_deleted_eq const&,
+                         friend_three_way_comparable_with_deleted_eq const&) = delete;
 };
 
 struct friend_three_way_comparable_with_deleted_ne {
-  friend auto
-  operator<=>(friend_three_way_comparable_with_deleted_ne const&,
-              friend_three_way_comparable_with_deleted_ne const&) = default;
-  friend bool
-  operator!=(friend_three_way_comparable_with_deleted_ne const&,
-             friend_three_way_comparable_with_deleted_ne const&) = delete;
+  friend auto operator<=>(friend_three_way_comparable_with_deleted_ne const&,
+                          friend_three_way_comparable_with_deleted_ne const&) = default;
+  friend bool operator!=(friend_three_way_comparable_with_deleted_ne const&,
+                         friend_three_way_comparable_with_deleted_ne const&) = delete;
 };
 
 struct one_way_eq {
@@ -270,9 +250,7 @@ struct one_way_ne {
 
   operator explicit_operators() const;
 };
-static_assert(requires(explicit_operators const x, one_way_ne const y) {
-  x != y;
-});
+static_assert(requires(explicit_operators const x, one_way_ne const y) { x != y; });
 
 struct explicit_bool {
   explicit operator bool() const noexcept;
@@ -283,10 +261,8 @@ struct totally_ordered_with_others {
 };
 
 struct no_lt_not_totally_ordered_with {
-  [[nodiscard]] bool
-  operator==(no_lt_not_totally_ordered_with const&) const = default;
-  [[nodiscard]] auto
-  operator<=>(no_lt_not_totally_ordered_with const&) const = default;
+  [[nodiscard]] bool operator==(no_lt_not_totally_ordered_with const&) const = default;
+  [[nodiscard]] auto operator<=>(no_lt_not_totally_ordered_with const&) const = default;
   operator totally_ordered_with_others() const noexcept;
 
   [[nodiscard]] bool operator==(totally_ordered_with_others const&) const;
@@ -295,10 +271,8 @@ struct no_lt_not_totally_ordered_with {
 };
 
 struct no_gt_not_totally_ordered_with {
-  [[nodiscard]] bool
-  operator==(no_gt_not_totally_ordered_with const&) const = default;
-  [[nodiscard]] auto
-  operator<=>(no_gt_not_totally_ordered_with const&) const = default;
+  [[nodiscard]] bool operator==(no_gt_not_totally_ordered_with const&) const = default;
+  [[nodiscard]] auto operator<=>(no_gt_not_totally_ordered_with const&) const = default;
   operator totally_ordered_with_others() const noexcept;
 
   [[nodiscard]] bool operator==(totally_ordered_with_others const&) const;
@@ -307,10 +281,8 @@ struct no_gt_not_totally_ordered_with {
 };
 
 struct no_le_not_totally_ordered_with {
-  [[nodiscard]] bool
-  operator==(no_le_not_totally_ordered_with const&) const = default;
-  [[nodiscard]] auto
-  operator<=>(no_le_not_totally_ordered_with const&) const = default;
+  [[nodiscard]] bool operator==(no_le_not_totally_ordered_with const&) const = default;
+  [[nodiscard]] auto operator<=>(no_le_not_totally_ordered_with const&) const = default;
   operator totally_ordered_with_others() const noexcept;
 
   [[nodiscard]] bool operator==(totally_ordered_with_others const&) const;
@@ -319,10 +291,8 @@ struct no_le_not_totally_ordered_with {
 };
 
 struct no_ge_not_totally_ordered_with {
-  [[nodiscard]] bool
-  operator==(no_ge_not_totally_ordered_with const&) const = default;
-  [[nodiscard]] auto
-  operator<=>(no_ge_not_totally_ordered_with const&) const = default;
+  [[nodiscard]] bool operator==(no_ge_not_totally_ordered_with const&) const = default;
+  [[nodiscard]] auto operator<=>(no_ge_not_totally_ordered_with const&) const = default;
   operator totally_ordered_with_others() const noexcept;
 
   [[nodiscard]] bool operator==(totally_ordered_with_others const&) const;
@@ -331,35 +301,28 @@ struct no_ge_not_totally_ordered_with {
 };
 
 struct partial_ordering_totally_ordered_with {
-  [[nodiscard]] auto operator<=>(
-      partial_ordering_totally_ordered_with const&) const noexcept = default;
-  [[nodiscard]] std::partial_ordering
-  operator<=>(totally_ordered_with_others const&) const noexcept;
+  [[nodiscard]] auto operator<=>(partial_ordering_totally_ordered_with const&) const noexcept = default;
+  [[nodiscard]] std::partial_ordering operator<=>(totally_ordered_with_others const&) const noexcept;
 
   operator totally_ordered_with_others() const;
 };
 
 struct weak_ordering_totally_ordered_with {
-  [[nodiscard]] auto operator<=>(
-      weak_ordering_totally_ordered_with const&) const noexcept = default;
-  [[nodiscard]] std::weak_ordering
-  operator<=>(totally_ordered_with_others const&) const noexcept;
+  [[nodiscard]] auto operator<=>(weak_ordering_totally_ordered_with const&) const noexcept = default;
+  [[nodiscard]] std::weak_ordering operator<=>(totally_ordered_with_others const&) const noexcept;
 
   operator totally_ordered_with_others() const;
 };
 
 struct strong_ordering_totally_ordered_with {
-  [[nodiscard]] auto operator<=>(
-      strong_ordering_totally_ordered_with const&) const noexcept = default;
-  [[nodiscard]] std::strong_ordering
-  operator<=>(totally_ordered_with_others const&) const noexcept;
+  [[nodiscard]] auto operator<=>(strong_ordering_totally_ordered_with const&) const noexcept = default;
+  [[nodiscard]] std::strong_ordering operator<=>(totally_ordered_with_others const&) const noexcept;
 
   operator totally_ordered_with_others() const;
 };
 
 struct eq_returns_explicit_bool {
-  friend explicit_bool operator==(eq_returns_explicit_bool,
-                                  eq_returns_explicit_bool);
+  friend explicit_bool operator==(eq_returns_explicit_bool, eq_returns_explicit_bool);
   friend bool operator!=(eq_returns_explicit_bool, eq_returns_explicit_bool);
   friend bool operator<(eq_returns_explicit_bool, eq_returns_explicit_bool);
   friend bool operator>(eq_returns_explicit_bool, eq_returns_explicit_bool);
@@ -368,10 +331,8 @@ struct eq_returns_explicit_bool {
 
   operator totally_ordered_with_others() const;
 
-  friend explicit_bool operator==(eq_returns_explicit_bool,
-                                  totally_ordered_with_others);
-  friend explicit_bool operator==(totally_ordered_with_others,
-                                  eq_returns_explicit_bool);
+  friend explicit_bool operator==(eq_returns_explicit_bool, totally_ordered_with_others);
+  friend explicit_bool operator==(totally_ordered_with_others, eq_returns_explicit_bool);
   friend bool operator!=(eq_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator!=(totally_ordered_with_others, eq_returns_explicit_bool);
   friend bool operator<(eq_returns_explicit_bool, totally_ordered_with_others);
@@ -386,8 +347,7 @@ struct eq_returns_explicit_bool {
 
 struct ne_returns_explicit_bool {
   friend bool operator==(ne_returns_explicit_bool, ne_returns_explicit_bool);
-  friend explicit_bool operator!=(ne_returns_explicit_bool,
-                                  ne_returns_explicit_bool);
+  friend explicit_bool operator!=(ne_returns_explicit_bool, ne_returns_explicit_bool);
   friend bool operator<(ne_returns_explicit_bool, ne_returns_explicit_bool);
   friend bool operator>(ne_returns_explicit_bool, ne_returns_explicit_bool);
   friend bool operator<=(ne_returns_explicit_bool, ne_returns_explicit_bool);
@@ -396,10 +356,8 @@ struct ne_returns_explicit_bool {
   operator totally_ordered_with_others() const;
 
   friend bool operator==(ne_returns_explicit_bool, totally_ordered_with_others);
-  friend explicit_bool operator!=(ne_returns_explicit_bool,
-                                  totally_ordered_with_others);
-  friend explicit_bool operator!=(totally_ordered_with_others,
-                                  ne_returns_explicit_bool);
+  friend explicit_bool operator!=(ne_returns_explicit_bool, totally_ordered_with_others);
+  friend explicit_bool operator!=(totally_ordered_with_others, ne_returns_explicit_bool);
   friend bool operator<(ne_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator<(totally_ordered_with_others, ne_returns_explicit_bool);
   friend bool operator>(ne_returns_explicit_bool, totally_ordered_with_others);
@@ -413,8 +371,7 @@ struct ne_returns_explicit_bool {
 struct lt_returns_explicit_bool {
   friend bool operator==(lt_returns_explicit_bool, lt_returns_explicit_bool);
   friend bool operator!=(lt_returns_explicit_bool, lt_returns_explicit_bool);
-  friend explicit_bool operator<(lt_returns_explicit_bool,
-                                 lt_returns_explicit_bool);
+  friend explicit_bool operator<(lt_returns_explicit_bool, lt_returns_explicit_bool);
   friend bool operator>(lt_returns_explicit_bool, lt_returns_explicit_bool);
   friend bool operator<=(lt_returns_explicit_bool, lt_returns_explicit_bool);
   friend bool operator>=(lt_returns_explicit_bool, lt_returns_explicit_bool);
@@ -424,8 +381,7 @@ struct lt_returns_explicit_bool {
   friend bool operator==(lt_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator!=(lt_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator!=(totally_ordered_with_others, lt_returns_explicit_bool);
-  friend explicit_bool operator<(lt_returns_explicit_bool,
-                                 totally_ordered_with_others);
+  friend explicit_bool operator<(lt_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator<(totally_ordered_with_others, lt_returns_explicit_bool);
   friend bool operator>(lt_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator>(totally_ordered_with_others, lt_returns_explicit_bool);
@@ -439,8 +395,7 @@ struct gt_returns_explicit_bool {
   friend bool operator==(gt_returns_explicit_bool, gt_returns_explicit_bool);
   friend bool operator!=(gt_returns_explicit_bool, gt_returns_explicit_bool);
   friend bool operator<(gt_returns_explicit_bool, gt_returns_explicit_bool);
-  friend explicit_bool operator>(gt_returns_explicit_bool,
-                                 gt_returns_explicit_bool);
+  friend explicit_bool operator>(gt_returns_explicit_bool, gt_returns_explicit_bool);
   friend bool operator<=(gt_returns_explicit_bool, gt_returns_explicit_bool);
   friend bool operator>=(gt_returns_explicit_bool, gt_returns_explicit_bool);
 
@@ -451,8 +406,7 @@ struct gt_returns_explicit_bool {
   friend bool operator!=(totally_ordered_with_others, gt_returns_explicit_bool);
   friend bool operator<(gt_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator<(totally_ordered_with_others, gt_returns_explicit_bool);
-  friend explicit_bool operator>(gt_returns_explicit_bool,
-                                 totally_ordered_with_others);
+  friend explicit_bool operator>(gt_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator>(totally_ordered_with_others, gt_returns_explicit_bool);
   friend bool operator<=(gt_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator<=(totally_ordered_with_others, gt_returns_explicit_bool);
@@ -465,8 +419,7 @@ struct le_returns_explicit_bool {
   friend bool operator!=(le_returns_explicit_bool, le_returns_explicit_bool);
   friend bool operator<(le_returns_explicit_bool, le_returns_explicit_bool);
   friend bool operator>(le_returns_explicit_bool, le_returns_explicit_bool);
-  friend explicit_bool operator<=(le_returns_explicit_bool,
-                                  le_returns_explicit_bool);
+  friend explicit_bool operator<=(le_returns_explicit_bool, le_returns_explicit_bool);
   friend bool operator>=(le_returns_explicit_bool, le_returns_explicit_bool);
 
   operator totally_ordered_with_others() const;
@@ -479,8 +432,7 @@ struct le_returns_explicit_bool {
   friend bool operator>(le_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator>(totally_ordered_with_others, le_returns_explicit_bool);
   friend bool operator<=(le_returns_explicit_bool, totally_ordered_with_others);
-  friend explicit_bool operator<=(totally_ordered_with_others,
-                                  le_returns_explicit_bool);
+  friend explicit_bool operator<=(totally_ordered_with_others, le_returns_explicit_bool);
   friend bool operator>=(le_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator>=(totally_ordered_with_others, le_returns_explicit_bool);
 };
@@ -491,8 +443,7 @@ struct ge_returns_explicit_bool {
   friend bool operator<(ge_returns_explicit_bool, ge_returns_explicit_bool);
   friend bool operator>(ge_returns_explicit_bool, ge_returns_explicit_bool);
   friend bool operator<=(ge_returns_explicit_bool, ge_returns_explicit_bool);
-  friend explicit_bool operator>=(ge_returns_explicit_bool,
-                                  ge_returns_explicit_bool);
+  friend explicit_bool operator>=(ge_returns_explicit_bool, ge_returns_explicit_bool);
 
   operator totally_ordered_with_others() const;
 
@@ -506,8 +457,7 @@ struct ge_returns_explicit_bool {
   friend bool operator<=(ge_returns_explicit_bool, totally_ordered_with_others);
   friend bool operator<=(totally_ordered_with_others, ge_returns_explicit_bool);
   friend bool operator>=(ge_returns_explicit_bool, totally_ordered_with_others);
-  friend explicit_bool operator>=(totally_ordered_with_others,
-                                  ge_returns_explicit_bool);
+  friend explicit_bool operator>=(totally_ordered_with_others, ge_returns_explicit_bool);
 };
 
 struct returns_true_type {
@@ -520,30 +470,18 @@ struct returns_true_type {
 
   operator totally_ordered_with_others() const;
 
-  friend std::true_type operator==(returns_true_type,
-                                   totally_ordered_with_others);
-  friend std::true_type operator==(totally_ordered_with_others,
-                                   returns_true_type);
-  friend std::true_type operator!=(returns_true_type,
-                                   totally_ordered_with_others);
-  friend std::true_type operator!=(totally_ordered_with_others,
-                                   returns_true_type);
-  friend std::true_type operator<(returns_true_type,
-                                  totally_ordered_with_others);
-  friend std::true_type operator<(totally_ordered_with_others,
-                                  returns_true_type);
-  friend std::true_type operator>(returns_true_type,
-                                  totally_ordered_with_others);
-  friend std::true_type operator>(totally_ordered_with_others,
-                                  returns_true_type);
-  friend std::true_type operator<=(returns_true_type,
-                                   totally_ordered_with_others);
-  friend std::true_type operator<=(totally_ordered_with_others,
-                                   returns_true_type);
-  friend std::true_type operator>=(returns_true_type,
-                                   totally_ordered_with_others);
-  friend std::true_type operator>=(totally_ordered_with_others,
-                                   returns_true_type);
+  friend std::true_type operator==(returns_true_type, totally_ordered_with_others);
+  friend std::true_type operator==(totally_ordered_with_others, returns_true_type);
+  friend std::true_type operator!=(returns_true_type, totally_ordered_with_others);
+  friend std::true_type operator!=(totally_ordered_with_others, returns_true_type);
+  friend std::true_type operator<(returns_true_type, totally_ordered_with_others);
+  friend std::true_type operator<(totally_ordered_with_others, returns_true_type);
+  friend std::true_type operator>(returns_true_type, totally_ordered_with_others);
+  friend std::true_type operator>(totally_ordered_with_others, returns_true_type);
+  friend std::true_type operator<=(returns_true_type, totally_ordered_with_others);
+  friend std::true_type operator<=(totally_ordered_with_others, returns_true_type);
+  friend std::true_type operator>=(returns_true_type, totally_ordered_with_others);
+  friend std::true_type operator>=(totally_ordered_with_others, returns_true_type);
 };
 
 struct returns_int_ptr {
@@ -570,4 +508,24 @@ struct returns_int_ptr {
   friend int* operator>=(totally_ordered_with_others, returns_int_ptr);
 };
 
-#endif // TEST_STD_CONCEPTS_COMPARISON_TYPES_H
+struct ForwardingTestObject {
+  constexpr bool operator<(ForwardingTestObject&&) && { return true; }
+  constexpr bool operator<(const ForwardingTestObject&) const& { return false; }
+
+  constexpr bool operator==(ForwardingTestObject&&) && { return true; }
+  constexpr bool operator==(const ForwardingTestObject&) const& { return false; }
+
+  constexpr bool operator!=(ForwardingTestObject&&) && { return true; }
+  constexpr bool operator!=(const ForwardingTestObject&) const& { return false; }
+
+  constexpr bool operator<=(ForwardingTestObject&&) && { return true; }
+  constexpr bool operator<=(const ForwardingTestObject&) const& { return false; }
+
+  constexpr bool operator>(ForwardingTestObject&&) && { return true; }
+  constexpr bool operator>(const ForwardingTestObject&) const& { return false; }
+
+  constexpr bool operator>=(ForwardingTestObject&&) && { return true; }
+  constexpr bool operator>=(const ForwardingTestObject&) const& { return false; }
+};
+
+#endif // TEST_SUPPORT_COMPARE_TYPES_H

diff  --git a/libcxx/test/support/pointer_comparison_test_helper.h b/libcxx/test/support/pointer_comparison_test_helper.h
new file mode 100644
index 0000000000000..c47d9ffd90bd3
--- /dev/null
+++ b/libcxx/test/support/pointer_comparison_test_helper.h
@@ -0,0 +1,54 @@
+#ifndef POINTER_COMPARISON_TEST_HELPER_H
+#define POINTER_COMPARISON_TEST_HELPER_H
+
+#include <cstdint>
+#include <cassert>
+
+#include "test_macros.h"
+
+template <template <class> class CompareTemplate>
+void do_pointer_comparison_test() {
+  typedef CompareTemplate<int*> Compare;
+  typedef CompareTemplate<std::uintptr_t> UIntCompare;
+#if TEST_STD_VER > 11
+  typedef CompareTemplate<void> VoidCompare;
+#else
+  typedef Compare VoidCompare;
+#endif
+
+  Compare comp;
+  UIntCompare ucomp;
+  VoidCompare vcomp;
+  struct {
+    int a, b;
+  } local;
+  int* pointers[] = {&local.a, &local.b, nullptr, &local.a + 1};
+  for (int* lhs : pointers) {
+    for (int* rhs : pointers) {
+      std::uintptr_t lhs_uint = reinterpret_cast<std::uintptr_t>(lhs);
+      std::uintptr_t rhs_uint = reinterpret_cast<std::uintptr_t>(rhs);
+      assert(comp(lhs, rhs) == ucomp(lhs_uint, rhs_uint));
+      assert(vcomp(lhs, rhs) == ucomp(lhs_uint, rhs_uint));
+    }
+  }
+}
+
+template <class Comp>
+void do_pointer_comparison_test(Comp comp) {
+  struct {
+    int a, b;
+  } local;
+  int* pointers[] = {&local.a, &local.b, nullptr, &local.a + 1};
+  for (int* lhs : pointers) {
+    for (int* rhs : pointers) {
+      std::uintptr_t lhs_uint = reinterpret_cast<std::uintptr_t>(lhs);
+      std::uintptr_t rhs_uint = reinterpret_cast<std::uintptr_t>(rhs);
+      void*          lhs_void = static_cast<void*>(lhs);
+      void*          rhs_void = static_cast<void*>(rhs);
+      assert(comp(lhs, rhs) == comp(lhs_uint, rhs_uint));
+      assert(comp(lhs_void, rhs_void) == comp(lhs_uint, rhs_uint));
+    }
+  }
+}
+
+#endif // POINTER_COMPARISON_TEST_HELPER_H


        


More information about the libcxx-commits mailing list