Message ID | 20191017154002.GK4169@redhat.com |
---|---|
State | New |
Headers | show |
Series | Define [range.cmp] comparisons for C++20 | expand |
On 17/10/19 16:40 +0100, Jonathan Wakely wrote: >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. This removes the dependency on std::less, so that ranges::less doesn't need to instantiate another template, and <bits/range_cmp.h> doesn't need to include <bits/stl_function.h>. Various components in <iterator> and <ranges> require ranges::less but don't necessarily need to depend on everything in <bits/stl_function.h>, so this removes unnecessary coupling between the new ranges world and the old STL world. Tested powerpc64le-linux, committed to trunk.
> commit b948d3f92d7bbe4d53237cb20ff40a15fa123988 > Author: Jonathan Wakely <jwakely@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(); > +}
On Wed, 23 Oct 2019 at 00:33, Tam S. B. <cpplearner@outlook.com> wrote: > > > commit b948d3f92d7bbe4d53237cb20ff40a15fa123988 > > Author: Jonathan Wakely <jwakely@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? Yes, I renamed the file and didn't fix the comment. It's already fixed locally and will be committed with the next round of changes (probably today). > > + * 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. OK, thanks, I'll guard it with #if.
On 23/10/19 08:08 +0100, Jonathan Wakely wrote: >On Wed, 23 Oct 2019 at 00:33, Tam S. B. <cpplearner@outlook.com> wrote: >> The use of concepts is causing `#include <functional>` to break on clang. > >OK, thanks, I'll guard it with #if. Fixed on trunk with this patch. My Clang 7.0.1 still can't compile current trunk though, because we now have a constexpr destructor on std::allocator. Thanks for the report.
On 25/10/19 14:34 +0100, Jonathan Wakely wrote: >On 23/10/19 08:08 +0100, Jonathan Wakely wrote: >>On Wed, 23 Oct 2019 at 00:33, Tam S. B. <cpplearner@outlook.com> wrote: >>>The use of concepts is causing `#include <functional>` to break on clang. >> >>OK, thanks, I'll guard it with #if. > >Fixed on trunk with this patch. My Clang 7.0.1 still can't compile current >trunk though, because we now have a constexpr destructor on >std::allocator. Which should be fixed by this, which I'll commit after testing finishes.
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 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 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(); +}