> commit b948d3f92d7bbe4d53237cb20ff40a15fa123988 > Author: Jonathan Wakely <jwak...@redhat.com> > Date: Thu Oct 17 15:20:38 2019 +0100 > > Define [range.cmp] comparisons for C++20 > > 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. > > diff --git a/libstdc++-v3/include/Makefile.am > b/libstdc++-v3/include/Makefile.am > index 35ee3cfcd34..9ff12f10fb1 100644 > --- a/libstdc++-v3/include/Makefile.am > +++ b/libstdc++-v3/include/Makefile.am > @@ -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 \ > diff --git a/libstdc++-v3/include/bits/range_cmp.h > b/libstdc++-v3/include/bits/range_cmp.h > new file mode 100644 > index 00000000000..3e5bb8847ab > --- /dev/null > +++ b/libstdc++-v3/include/bits/range_cmp.h > @@ -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 does not match the actual filename. Seems like a typo? > + * 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) The use of concepts is causing `#include <functional>` to break on clang. > + { 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 > diff --git a/libstdc++-v3/include/std/functional > b/libstdc++-v3/include/std/functional > index 30576f23d35..7ad29a1a335 100644 > --- a/libstdc++-v3/include/std/functional > +++ b/libstdc++-v3/include/std/functional > @@ -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 > index 00000000000..fd9b79f1fcd > --- /dev/null > +++ b/libstdc++-v3/testsuite/20_util/function_objects/identity/1.cc > @@ -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 > index 00000000000..c3ceb316a58 > --- /dev/null > +++ b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/equal_to.cc > @@ -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 > index 00000000000..87fd518e146 > --- /dev/null > +++ b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/greater.cc > @@ -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 > index 00000000000..a1972ab1c09 > --- /dev/null > +++ > b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/greater_equal.cc > @@ -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 > index 00000000000..e484628f76f > --- /dev/null > +++ b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less.cc > @@ -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 > index 00000000000..7f5bee68eb4 > --- /dev/null > +++ b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/less_equal.cc > @@ -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 > index 00000000000..857e63426aa > --- /dev/null > +++ > b/libstdc++-v3/testsuite/20_util/function_objects/range.cmp/not_equal_to.cc > @@ -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(); > +}