public inbox for libstdc++@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Define [range.cmp] comparisons for C++20
@ 2019-10-17 15:40 Jonathan Wakely
  2019-10-18 11:26 ` Jonathan Wakely
  2019-10-22 23:33 ` Tam S. B.
  0 siblings, 2 replies; 6+ messages in thread
From: Jonathan Wakely @ 2019-10-17 15:40 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 907 bytes --]

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.

Tested powerpc64le-linux, committed to trunk.



[-- Attachment #2: patch.txt --]
[-- Type: text/plain, Size: 27457 bytes --]

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 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();
+}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Define [range.cmp] comparisons for C++20
  2019-10-17 15:40 [PATCH] Define [range.cmp] comparisons for C++20 Jonathan Wakely
@ 2019-10-18 11:26 ` Jonathan Wakely
  2019-10-22 23:33 ` Tam S. B.
  1 sibling, 0 replies; 6+ messages in thread
From: Jonathan Wakely @ 2019-10-18 11:26 UTC (permalink / raw)
  To: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1384 bytes --]

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.


[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 1425 bytes --]

commit cc43d4d492ecc64cc3aac8b47aae759942d9e57f
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Thu Oct 17 18:56:46 2019 +0100

    Implement std::ranges::less without std::less
    
            * include/bits/range_cmp.h (ranges::less::operator()): Inline the
            logic from std::less::operator() to remove the dependency on it.

diff --git a/libstdc++-v3/include/bits/range_cmp.h b/libstdc++-v3/include/bits/range_cmp.h
index 3e5bb8847ab..a77fd5274b9 100644
--- a/libstdc++-v3/include/bits/range_cmp.h
+++ b/libstdc++-v3/include/bits/range_cmp.h
@@ -121,10 +121,19 @@ namespace ranges
       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)),
+	  {
+#ifdef __cpp_lib_is_constant_evaluated
+	    if (std::is_constant_evaluated())
+	      return __t < __u;
+#endif
+	    auto __x = reinterpret_cast<__UINTPTR_TYPE__>(
+	      static_cast<const volatile void*>(std::forward<_Tp>(__t)));
+	    auto __y = reinterpret_cast<__UINTPTR_TYPE__>(
 	      static_cast<const volatile void*>(std::forward<_Up>(__u)));
-	return std::forward<_Tp>(__t) < std::forward<_Up>(__u);
+	    return __x < __y;
+	  }
+	else
+	  return std::forward<_Tp>(__t) < std::forward<_Up>(__u);
       }
 
     using is_transparent = __is_transparent;

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Define [range.cmp] comparisons for C++20
  2019-10-17 15:40 [PATCH] Define [range.cmp] comparisons for C++20 Jonathan Wakely
  2019-10-18 11:26 ` Jonathan Wakely
@ 2019-10-22 23:33 ` Tam S. B.
  2019-10-23  7:08   ` Jonathan Wakely
  1 sibling, 1 reply; 6+ messages in thread
From: Tam S. B. @ 2019-10-22 23:33 UTC (permalink / raw)
  To: Jonathan Wakely, libstdc++, gcc-patches

> 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();
> +}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Define [range.cmp] comparisons for C++20
  2019-10-22 23:33 ` Tam S. B.
@ 2019-10-23  7:08   ` Jonathan Wakely
  2019-10-25 13:34     ` Jonathan Wakely
  0 siblings, 1 reply; 6+ messages in thread
From: Jonathan Wakely @ 2019-10-23  7:08 UTC (permalink / raw)
  To: Tam S. B.; +Cc: Jonathan Wakely, libstdc++, gcc-patches

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.

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Define [range.cmp] comparisons for C++20
  2019-10-23  7:08   ` Jonathan Wakely
@ 2019-10-25 13:34     ` Jonathan Wakely
  2019-10-25 13:49       ` Jonathan Wakely
  0 siblings, 1 reply; 6+ messages in thread
From: Jonathan Wakely @ 2019-10-25 13:34 UTC (permalink / raw)
  To: Tam S. B.; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 426 bytes --]

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.


[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 1287 bytes --]

commit 27274f130d7c3cf8a6ccbf27c24368fbbf2fb3fb
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Oct 25 14:26:54 2019 +0100

    Guard use of concepts with feature test macro
    
    This fixes a regression when using Clang.
    
            * include/bits/range_cmp.h: Check __cpp_lib_concepts before defining
            concepts. Fix comment.

diff --git a/libstdc++-v3/include/bits/range_cmp.h b/libstdc++-v3/include/bits/range_cmp.h
index a77fd5274b9..870eb3a8ee5 100644
--- a/libstdc++-v3/include/bits/range_cmp.h
+++ b/libstdc++-v3/include/bits/range_cmp.h
@@ -22,7 +22,7 @@
 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 // <http://www.gnu.org/licenses/>.
 
-/** @file bits/ranges_function.h
+/** @file bits/range_cmp.h
  *  This is an internal header file, included by other library headers.
  *  Do not attempt to use it directly. @headername{functional}
  */
@@ -54,6 +54,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     using is_transparent = __is_transparent;
   };
 
+#ifdef __cpp_lib_concepts
 namespace ranges
 {
   namespace __detail
@@ -182,6 +183,7 @@ namespace ranges
   };
 
 } // namespace ranges
+#endif // library concepts
 _GLIBCXX_END_NAMESPACE_VERSION
 } // namespace std
 #endif // C++20

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] Define [range.cmp] comparisons for C++20
  2019-10-25 13:34     ` Jonathan Wakely
@ 2019-10-25 13:49       ` Jonathan Wakely
  0 siblings, 0 replies; 6+ messages in thread
From: Jonathan Wakely @ 2019-10-25 13:49 UTC (permalink / raw)
  To: Tam S. B.; +Cc: libstdc++, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 534 bytes --]

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.


[-- Attachment #2: patch.txt --]
[-- Type: text/x-patch, Size: 2473 bytes --]

commit 063495404380ebe3d28429c6ce718cd05c8d5451
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Fri Oct 25 14:43:23 2019 +0100

    Fix compilation with Clang
    
    The new constexpr destructor on std::allocator breaks compilation with
    Clang in C++2a mode. This only makes it constexpr if the compiler
    supports the P0784R7 features.
    
            * include/bits/allocator.h: Check __cpp_constexpr_dynamic_alloc
            before making the std::allocator destructor constexpr.
            * testsuite/20_util/allocator/requirements/constexpr.cc: New test.

diff --git a/libstdc++-v3/include/bits/allocator.h b/libstdc++-v3/include/bits/allocator.h
index 2559c57b12e..00d7461e42e 100644
--- a/libstdc++-v3/include/bits/allocator.h
+++ b/libstdc++-v3/include/bits/allocator.h
@@ -160,7 +160,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	_GLIBCXX20_CONSTEXPR
 	allocator(const allocator<_Tp1>&) _GLIBCXX_NOTHROW { }
 
-      _GLIBCXX20_CONSTEXPR
+#if __cpp_constexpr_dynamic_alloc
+      constexpr
+#endif
       ~allocator() _GLIBCXX_NOTHROW { }
 
 #if __cplusplus > 201703L
diff --git a/libstdc++-v3/testsuite/20_util/allocator/requirements/constexpr.cc b/libstdc++-v3/testsuite/20_util/allocator/requirements/constexpr.cc
new file mode 100644
index 00000000000..6a6dbf1833f
--- /dev/null
+++ b/libstdc++-v3/testsuite/20_util/allocator/requirements/constexpr.cc
@@ -0,0 +1,28 @@
+// 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 <memory>
+
+constexpr bool f()
+{
+  std::allocator<int> a;
+  return std::allocator_traits<std::allocator<int>>::max_size(a) > 0;
+}
+static_assert( f() );

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2019-10-25 13:49 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-17 15:40 [PATCH] Define [range.cmp] comparisons for C++20 Jonathan Wakely
2019-10-18 11:26 ` Jonathan Wakely
2019-10-22 23:33 ` Tam S. B.
2019-10-23  7:08   ` Jonathan Wakely
2019-10-25 13:34     ` Jonathan Wakely
2019-10-25 13:49       ` Jonathan Wakely

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).