Define [range.cmp] comparisons for C++20
authorJonathan Wakely <jwakely@redhat.com>
Thu, 17 Oct 2019 15:40:00 +0000 (16:40 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 17 Oct 2019 15:40:00 +0000 (16:40 +0100)
Define std::identity, std::ranges::equal_to, std::ranges::not_equal_to,
std::ranges::greater, std::ranges::less, std::ranges::greater_equal and
std::ranges::less_equal.

* include/Makefile.am: Add new header.
* include/Makefile.in: Regenerate.
* include/bits/range_cmp.h: New header for C++20 function objects.
* include/std/functional: Include new header.
* testsuite/20_util/function_objects/identity/1.cc: New test.
* testsuite/20_util/function_objects/range.cmp/equal_to.cc: New test.
* testsuite/20_util/function_objects/range.cmp/greater.cc: New test.
* testsuite/20_util/function_objects/range.cmp/greater_equal.cc: New
test.
* testsuite/20_util/function_objects/range.cmp/less.cc: New test.
* testsuite/20_util/function_objects/range.cmp/less_equal.cc: New test.
* testsuite/20_util/function_objects/range.cmp/not_equal_to.cc: New
test.

From-SVN: r277120

12 files changed:
libstdc++-v3/ChangeLog
libstdc++-v3/include/Makefile.am
libstdc++-v3/include/Makefile.in
libstdc++-v3/include/bits/range_cmp.h [new file with mode: 0644]
libstdc++-v3/include/std/functional
libstdc++-v3/testsuite/20_util/function_objects/identity/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/function_objects/range.cmp/equal_to.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/function_objects/range.cmp/greater.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/function_objects/range.cmp/greater_equal.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less_equal.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/function_objects/range.cmp/not_equal_to.cc [new file with mode: 0644]

index 4c268795fdd1464e2900bce5094f02e74b256c9d..324955c692a4d2881122f311dfd274fbc7365d33 100644 (file)
@@ -1,5 +1,19 @@
 2019-10-17  Jonathan Wakely  <jwakely@redhat.com>
 
+       * include/Makefile.am: Add new header.
+       * include/Makefile.in: Regenerate.
+       * include/bits/range_cmp.h: New header for C++20 function objects.
+       * include/std/functional: Include new header.
+       * testsuite/20_util/function_objects/identity/1.cc: New test.
+       * testsuite/20_util/function_objects/range.cmp/equal_to.cc: New test.
+       * testsuite/20_util/function_objects/range.cmp/greater.cc: New test.
+       * testsuite/20_util/function_objects/range.cmp/greater_equal.cc: New
+       test.
+       * testsuite/20_util/function_objects/range.cmp/less.cc: New test.
+       * testsuite/20_util/function_objects/range.cmp/less_equal.cc: New test.
+       * testsuite/20_util/function_objects/range.cmp/not_equal_to.cc: New
+       test.
+
        PR libstdc++/92124
        * include/bits/forward_list.h
        (_M_move_assign(forward_list&&, false_type)): Do not use
index 35ee3cfcd344d50c037dfd186dac472ca18e76d6..9ff12f10fb1a08dff4b6d5ad8bff5837cfcb4a02 100644 (file)
@@ -152,6 +152,7 @@ bits_headers = \
        ${bits_srcdir}/random.h \
        ${bits_srcdir}/random.tcc \
        ${bits_srcdir}/range_access.h \
+       ${bits_srcdir}/range_cmp.h \
        ${bits_srcdir}/refwrap.h \
        ${bits_srcdir}/regex.h \
        ${bits_srcdir}/regex.tcc \
index 5d0488846ffb6cebb7c7cdcb85c6091dc165440e..5dce01faeda4261a6a9f2b2498b429c98cd01fa6 100644 (file)
@@ -496,6 +496,7 @@ bits_headers = \
        ${bits_srcdir}/random.h \
        ${bits_srcdir}/random.tcc \
        ${bits_srcdir}/range_access.h \
+       ${bits_srcdir}/range_cmp.h \
        ${bits_srcdir}/refwrap.h \
        ${bits_srcdir}/regex.h \
        ${bits_srcdir}/regex.tcc \
diff --git a/libstdc++-v3/include/bits/range_cmp.h b/libstdc++-v3/include/bits/range_cmp.h
new file mode 100644 (file)
index 0000000..3e5bb88
--- /dev/null
@@ -0,0 +1,179 @@
+// Concept-constrained comparison implementations -*- C++ -*-
+
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/ranges_function.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{functional}
+ */
+
+#ifndef _RANGE_CMP_H
+#define _RANGE_CMP_H 1
+
+#if __cplusplus > 201703L
+# include <bits/move.h>
+# include <concepts>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  struct __is_transparent; // not defined
+
+  // Define std::identity here so that <iterator> and <ranges>
+  // don't need to include <bits/stl_function.h> to get it.
+
+  /// [func.identity] The identity function.
+  struct identity
+  {
+    template<typename _Tp>
+      constexpr _Tp&&
+      operator()(_Tp&& __t) const noexcept
+      { return std::forward<_Tp>(__t); }
+
+    using is_transparent = __is_transparent;
+  };
+
+namespace ranges
+{
+  namespace __detail
+  {
+    // BUILTIN-PTR-CMP(T, ==, U)
+    template<typename _Tp, typename _Up>
+      concept __eq_builtin_ptr_cmp
+       = convertible_to<_Tp, const volatile void*>
+         && convertible_to<_Up, const volatile void*>
+         && (! requires(_Tp&& __t, _Up&& __u)
+             { operator==(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
+             &&
+             ! requires(_Tp&& __t, _Up&& __u)
+             { std::forward<_Tp>(__t).operator==(std::forward<_Up>(__u)); });
+
+    // BUILTIN-PTR-CMP(T, <, U)
+    template<typename _Tp, typename _Up>
+      concept __less_builtin_ptr_cmp
+       = convertible_to<_Tp, const volatile void*>
+         && convertible_to<_Up, const volatile void*>
+         && (! requires(_Tp&& __t, _Up&& __u)
+             { operator<(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
+             && ! requires(_Tp&& __t, _Up&& __u)
+             { std::forward<_Tp>(__t).operator<(std::forward<_Up>(__u)); });
+  } // namespace __detail
+
+  // [range.cmp] Concept-constrained comparisons
+
+  /// ranges::equal_to function object type.
+  struct equal_to
+  {
+    template<typename _Tp, typename _Up>
+      requires equality_comparable_with<_Tp, _Up>
+       || __detail::__eq_builtin_ptr_cmp<_Tp, _Up>
+      constexpr bool
+      operator()(_Tp&& __t, _Up&& __u) const
+      noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>()))
+      { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); }
+
+    using is_transparent = __is_transparent;
+  };
+
+  /// ranges::not_equal_to function object type.
+  struct not_equal_to
+  {
+    template<typename _Tp, typename _Up>
+      requires equality_comparable_with<_Tp, _Up>
+       || __detail::__eq_builtin_ptr_cmp<_Tp, _Up>
+      constexpr bool
+      operator()(_Tp&& __t, _Up&& __u) const
+      noexcept(noexcept(std::declval<_Up>() == std::declval<_Tp>()))
+      { return !equal_to{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
+
+    using is_transparent = __is_transparent;
+  };
+
+  /// ranges::less function object type.
+  struct less
+  {
+    template<typename _Tp, typename _Up>
+      requires totally_ordered_with<_Tp, _Up>
+       || __detail::__less_builtin_ptr_cmp<_Tp, _Up>
+      constexpr bool
+      operator()(_Tp&& __t, _Up&& __u) const
+      noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>()))
+      {
+       if constexpr (__detail::__less_builtin_ptr_cmp<_Tp, _Up>)
+         return std::less<const volatile void*>{}(
+             static_cast<const volatile void*>(std::forward<_Tp>(__t)),
+             static_cast<const volatile void*>(std::forward<_Up>(__u)));
+       return std::forward<_Tp>(__t) < std::forward<_Up>(__u);
+      }
+
+    using is_transparent = __is_transparent;
+  };
+
+  /// ranges::greater function object type.
+  struct greater
+  {
+    template<typename _Tp, typename _Up>
+      requires totally_ordered_with<_Tp, _Up>
+       || __detail::__less_builtin_ptr_cmp<_Up, _Tp>
+      constexpr bool
+      operator()(_Tp&& __t, _Up&& __u) const
+      noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>()))
+      { return less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); }
+
+    using is_transparent = __is_transparent;
+  };
+
+  /// ranges::greater_equal function object type.
+  struct greater_equal
+  {
+    template<typename _Tp, typename _Up>
+      requires totally_ordered_with<_Tp, _Up>
+       || __detail::__less_builtin_ptr_cmp<_Tp, _Up>
+      constexpr bool
+      operator()(_Tp&& __t, _Up&& __u) const
+      noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>()))
+      { return !less{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); }
+
+    using is_transparent = __is_transparent;
+  };
+
+  /// ranges::less_equal function object type.
+  struct less_equal
+  {
+    template<typename _Tp, typename _Up>
+      requires totally_ordered_with<_Tp, _Up>
+       || __detail::__less_builtin_ptr_cmp<_Up, _Tp>
+      constexpr bool
+      operator()(_Tp&& __t, _Up&& __u) const
+      noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>()))
+      { return !less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); }
+
+    using is_transparent = __is_transparent;
+  };
+
+} // namespace ranges
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+#endif // C++20
+#endif // _RANGE_CMP_H
index 30576f23d35fc8b1a09815bf0b129afaeec5a20b..7ad29a1a335b64a086b4a28c4743af81ba735e51 100644 (file)
@@ -64,6 +64,9 @@
 # include <utility>
 # include <bits/stl_algo.h>
 #endif
+#if __cplusplus > 201703L
+# include <bits/range_cmp.h>
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/identity/1.cc b/libstdc++-v3/testsuite/20_util/function_objects/identity/1.cc
new file mode 100644 (file)
index 0000000..fd9b79f
--- /dev/null
@@ -0,0 +1,40 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <functional>
+
+// C++20 [func.identity]
+static_assert( std::is_default_constructible_v<std::identity> );
+static_assert( std::is_copy_constructible_v<std::identity> );
+static_assert( std::is_move_constructible_v<std::identity> );
+static_assert( std::is_copy_assignable_v<std::identity> );
+static_assert( std::is_move_assignable_v<std::identity> );
+
+static_assert( !std::is_invocable_v<std::identity> );
+static_assert( !std::is_invocable_v<std::identity, int&, int&> );
+static_assert( std::is_nothrow_invocable_r_v<int&, std::identity&, int&> );
+static_assert( std::is_nothrow_invocable_r_v<const long&, std::identity, const long&> );
+static_assert( std::is_nothrow_invocable_r_v<short&&, const std::identity&, short> );
+static_assert( std::is_nothrow_invocable_r_v<const char&&, const std::identity, const char> );
+
+int i;
+static_assert( std::addressof(std::identity{}(i)) == std::addressof(i) );
+
+using T = std::identity::is_transparent; // required typedef
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/equal_to.cc b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/equal_to.cc
new file mode 100644 (file)
index 0000000..c3ceb31
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+// C++20 [range.cmp]
+
+using F = std::ranges::equal_to;
+static_assert( std::is_default_constructible_v<F> );
+static_assert( std::is_copy_constructible_v<F> );
+static_assert( std::is_move_constructible_v<F> );
+static_assert( std::is_copy_assignable_v<F> );
+static_assert( std::is_move_assignable_v<F> );
+
+static_assert( ! std::is_invocable_v<F> );
+static_assert( ! std::is_invocable_v<F, int&> );
+static_assert( ! std::is_invocable_v<F, int, void> );
+static_assert( ! std::is_invocable_v<F, int, void*> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, int&, int> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F, const long&, char> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F&, short, int&> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F, const char, char> );
+
+using T = F::is_transparent; // required typedef
+
+static_assert( std::ranges::equal_to{}(99, 99.0) );
+static_assert( ! std::ranges::equal_to{}(99, 99.01) );
+static_assert( ! std::ranges::equal_to{}(99, 140L) );
+
+void
+test01()
+{
+  F f;
+  int a[2]{};
+  VERIFY( f(&a, (void*)&a[0]) );
+  VERIFY( ! f(&a, (void*)&a[1]) );
+  VERIFY( f(&a + 1, (void*)(a + 2)) );
+}
+
+struct X { };
+int operator==(X, X) noexcept { return 2; }
+int operator!=(X, X) { return 0; }
+
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, X, X> );
+
+void
+test02()
+{
+  X x;
+  F f;
+  VERIFY( f(x, x) );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/greater.cc b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/greater.cc
new file mode 100644 (file)
index 0000000..87fd518
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+// C++20 [range.cmp]
+
+using F = std::ranges::greater;
+static_assert( std::is_default_constructible_v<F> );
+static_assert( std::is_copy_constructible_v<F> );
+static_assert( std::is_move_constructible_v<F> );
+static_assert( std::is_copy_assignable_v<F> );
+static_assert( std::is_move_assignable_v<F> );
+
+static_assert( ! std::is_invocable_v<F> );
+static_assert( ! std::is_invocable_v<F, int&> );
+static_assert( ! std::is_invocable_v<F, int, void> );
+static_assert( ! std::is_invocable_v<F, int, void*> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, int&, int> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F, const long&, char> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F&, short, int&> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F, const char, char> );
+
+using T = F::is_transparent; // required typedef
+
+static_assert( ! std::ranges::greater{}(99, 99.0) );
+static_assert( std::ranges::greater{}(99.01, 99) );
+static_assert( std::ranges::greater{}(990, 140L) );
+
+void
+test01()
+{
+  F f;
+  int a[2]{};
+  VERIFY( ! f(&a, (void*)&a[0]) );
+  VERIFY( f((void*)&a[1], &a) );
+  VERIFY( f(&a + 1, (void*)(a + 1)) );
+  VERIFY( ! f(&a, (void*)(a + 1)) );
+}
+
+struct X { };
+int operator==(X, X) { return 2; }
+int operator!=(X, X) { return 0; }
+int operator<(X, X) noexcept { return 0; }
+int operator>(X, X) { return 0; }
+int operator<=(X, X) { return 3; }
+int operator>=(X, X) { return 4; }
+
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, X, X> );
+
+void
+test02()
+{
+  X x;
+  F f;
+  VERIFY( ! f(x, x) );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/greater_equal.cc b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/greater_equal.cc
new file mode 100644 (file)
index 0000000..a1972ab
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+// C++20 [range.cmp]
+
+using F = std::ranges::greater_equal;
+static_assert( std::is_default_constructible_v<F> );
+static_assert( std::is_copy_constructible_v<F> );
+static_assert( std::is_move_constructible_v<F> );
+static_assert( std::is_copy_assignable_v<F> );
+static_assert( std::is_move_assignable_v<F> );
+
+static_assert( ! std::is_invocable_v<F> );
+static_assert( ! std::is_invocable_v<F, int&> );
+static_assert( ! std::is_invocable_v<F, int, void> );
+static_assert( ! std::is_invocable_v<F, int, void*> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, int&, int> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F, const long&, char> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F&, short, int&> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F, const char, char> );
+
+using T = F::is_transparent; // required typedef
+
+static_assert( std::ranges::greater_equal{}(99, 99.0) );
+static_assert( std::ranges::greater_equal{}(99.01, 99) );
+static_assert( ! std::ranges::greater_equal{}(99, 140L) );
+
+void
+test01()
+{
+  F f;
+  int a[2]{};
+  VERIFY( f(&a, (void*)&a[0]) );
+  VERIFY( f((void*)&a[1], &a) );
+  VERIFY( f(&a + 1, (void*)(a + 1)) );
+  VERIFY( ! f(&a, (void*)(a + 1)) );
+}
+
+struct X { };
+int operator==(X, X) { return 2; }
+int operator!=(X, X) { return 0; }
+int operator<(X, X) noexcept { return 0; }
+int operator>(X, X) { return 0; }
+int operator<=(X, X) { return 3; }
+int operator>=(X, X) { return 4; }
+
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, X, X> );
+
+void
+test02()
+{
+  X x;
+  F f;
+  VERIFY( f(x, x) );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less.cc b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less.cc
new file mode 100644 (file)
index 0000000..e484628
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+// C++20 [range.cmp]
+
+using F = std::ranges::less;
+static_assert( std::is_default_constructible_v<F> );
+static_assert( std::is_copy_constructible_v<F> );
+static_assert( std::is_move_constructible_v<F> );
+static_assert( std::is_copy_assignable_v<F> );
+static_assert( std::is_move_assignable_v<F> );
+
+static_assert( ! std::is_invocable_v<F> );
+static_assert( ! std::is_invocable_v<F, int&> );
+static_assert( ! std::is_invocable_v<F, int, void> );
+static_assert( ! std::is_invocable_v<F, int, void*> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, int&, int> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F, const long&, char> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F&, short, int&> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F, const char, char> );
+
+using T = F::is_transparent; // required typedef
+
+static_assert( ! std::ranges::less{}(99, 99.0) );
+static_assert( std::ranges::less{}(99, 99.01) );
+static_assert( std::ranges::less{}(99, 140L) );
+
+void
+test01()
+{
+  F f;
+  int a[2]{};
+  VERIFY( ! f(&a, (void*)&a[0]) );
+  VERIFY( f(&a, (void*)&a[1]) );
+  VERIFY( ! f(&a + 1, (void*)(a + 2)) );
+  VERIFY( f(&a, (void*)(a + 1)) );
+}
+
+struct X { };
+int operator==(X, X) { return 2; }
+int operator!=(X, X) { return 0; }
+int operator<(X, X) noexcept { return 0; }
+int operator>(X, X) { return 0; }
+int operator<=(X, X) { return 3; }
+int operator>=(X, X) { return 4; }
+
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, X, X> );
+
+void
+test02()
+{
+  X x;
+  F f;
+  VERIFY( ! f(x, x) );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less_equal.cc b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less_equal.cc
new file mode 100644 (file)
index 0000000..7f5bee6
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+// C++20 [range.cmp]
+
+using F = std::ranges::less_equal;
+static_assert( std::is_default_constructible_v<F> );
+static_assert( std::is_copy_constructible_v<F> );
+static_assert( std::is_move_constructible_v<F> );
+static_assert( std::is_copy_assignable_v<F> );
+static_assert( std::is_move_assignable_v<F> );
+
+static_assert( ! std::is_invocable_v<F> );
+static_assert( ! std::is_invocable_v<F, int&> );
+static_assert( ! std::is_invocable_v<F, int, void> );
+static_assert( ! std::is_invocable_v<F, int, void*> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, int&, int> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F, const long&, char> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F&, short, int&> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F, const char, char> );
+
+using T = F::is_transparent; // required typedef
+
+static_assert( std::ranges::less_equal{}(99, 99.0) );
+static_assert( ! std::ranges::less_equal{}(99.01, 99) );
+static_assert( std::ranges::less_equal{}(99, 140L) );
+
+void
+test01()
+{
+  F f;
+  int a[2]{};
+  VERIFY( f(&a, (void*)&a[0]) );
+  VERIFY( ! f((void*)&a[1], &a) );
+  VERIFY( ! f(&a + 1, (void*)(a + 1)) );
+  VERIFY( f(&a, (void*)(a + 1)) );
+}
+
+struct X { };
+int operator==(X, X) { return 2; }
+int operator!=(X, X) { return 0; }
+int operator<(X, X) noexcept { return 0; }
+int operator>(X, X) { return 0; }
+int operator<=(X, X) { return 3; }
+int operator>=(X, X) { return 4; }
+
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, X, X> );
+
+void
+test02()
+{
+  X x;
+  F f;
+  VERIFY( f(x, x) );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/not_equal_to.cc b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/not_equal_to.cc
new file mode 100644 (file)
index 0000000..857e634
--- /dev/null
@@ -0,0 +1,77 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <functional>
+#include <testsuite_hooks.h>
+
+// C++20 [range.cmp]
+
+using F = std::ranges::not_equal_to;
+static_assert( std::is_default_constructible_v<F> );
+static_assert( std::is_copy_constructible_v<F> );
+static_assert( std::is_move_constructible_v<F> );
+static_assert( std::is_copy_assignable_v<F> );
+static_assert( std::is_move_assignable_v<F> );
+
+static_assert( ! std::is_invocable_v<F> );
+static_assert( ! std::is_invocable_v<F, int&> );
+static_assert( ! std::is_invocable_v<F, int, void> );
+static_assert( ! std::is_invocable_v<F, int, void*> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, int&, int> );
+static_assert( std::is_nothrow_invocable_r_v<bool, F, const long&, char> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F&, short, int&> );
+static_assert( std::is_nothrow_invocable_r_v<bool, const F, const char, char> );
+
+using T = F::is_transparent; // required typedef
+
+static_assert( ! std::ranges::not_equal_to{}(99, 99.0) );
+static_assert( std::ranges::not_equal_to{}(99, 99.01) );
+static_assert( std::ranges::not_equal_to{}(99, 140L) );
+
+void
+test01()
+{
+  F f;
+  int a[2]{};
+  VERIFY( ! f(&a, (void*)&a[0]) );
+  VERIFY( f(&a, (void*)&a[1]) );
+  VERIFY( ! f(&a + 1, (void*)(a + 2)) );
+}
+
+struct X { };
+int operator==(X, X) noexcept { return 2; }
+int operator!=(X, X) { return 0; }
+
+static_assert( std::is_nothrow_invocable_r_v<bool, F&, X, X> );
+
+void
+test02()
+{
+  X x;
+  F f;
+  VERIFY( ! f(x, x) );
+}
+
+int
+main()
+{
+  test01();
+  test02();
+}