[committed] libstdc++: Remove workarounds for constraints on alias templates

Message ID 20200205151453.GA854252@redhat.com
State New
Headers show
Series
  • [committed] libstdc++: Remove workarounds for constraints on alias templates
Related show

Commit Message

Jonathan Wakely Feb. 5, 2020, 3:14 p.m.
The G++ bug has been fixed for a couple of months so we can remove these
workarounds that define alias templates in terms of constrained class
templates. We can just apply constraints directly to alias templates as
specified in the C++20 working draft.

	* include/bits/iterator_concepts.h (iter_reference_t)
	(iter_rvalue_reference_t, iter_common_reference_t, indirect_result_t):
	Remove workarounds for PR c++/67704.
	* testsuite/24_iterators/aliases.cc: New test.

Tested powerpc64le-linux, committed to master.
commit 269e8130b77065452698ab97e5da77d132d00276
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Wed Feb 5 10:35:19 2020 +0000

    libstdc++: Remove workarounds for constraints on alias templates
    
    The G++ bug has been fixed for a couple of months so we can remove these
    workarounds that define alias templates in terms of constrained class
    templates. We can just apply constraints directly to alias templates as
    specified in the C++20 working draft.
    
            * include/bits/iterator_concepts.h (iter_reference_t)
            (iter_rvalue_reference_t, iter_common_reference_t, indirect_result_t):
            Remove workarounds for PR c++/67704.
            * testsuite/24_iterators/aliases.cc: New test.

Patch

diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index bf581597229..d9b8958d0a7 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -70,17 +70,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	{
 	  { *__t } -> __can_reference;
 	};
-
-    // FIXME: needed due to PR c++/67704
-    template<__detail::__dereferenceable _Tp>
-      struct __iter_ref
-      {
-	using type = decltype(*std::declval<_Tp&>());
-      };
   } // namespace __detail
 
-  template<typename _Tp>
-    using iter_reference_t = typename __detail::__iter_ref<_Tp>::type;
+  template<__detail::__dereferenceable _Tp>
+    using iter_reference_t = decltype(*std::declval<_Tp&>());
 
   namespace ranges
   {
@@ -127,26 +120,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     } // inline namespace __cust
   } // namespace ranges
 
-  namespace __detail
-  {
-    // FIXME: needed due to PR c++/67704
-    template<__detail::__dereferenceable _Tp>
-      struct __iter_rvalue_ref
-      { };
-
-    template<__detail::__dereferenceable _Tp>
-      requires requires(_Tp& __t)
-      {
-	{ ranges::iter_move(__t) } -> __detail::__can_reference;
-      }
-      struct __iter_rvalue_ref<_Tp>
-      { using type = decltype(ranges::iter_move(std::declval<_Tp&>())); };
-
-  } // namespace __detail
-
-  template<typename _Tp>
+  template<__detail::__dereferenceable _Tp>
+    requires requires(_Tp& __t)
+    { { ranges::iter_move(__t) } -> __detail::__can_reference; }
     using iter_rvalue_reference_t
-      = typename __detail::__iter_rvalue_ref<_Tp>::type;
+      = decltype(ranges::iter_move(std::declval<_Tp&>()));
 
   template<typename> struct incrementable_traits { };
 
@@ -467,18 +445,9 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       && common_reference_with<iter_rvalue_reference_t<_In>&&,
 			       const iter_value_t<_In>&>;
 
-  namespace __detail
-  {
-    // FIXME: needed due to PR c++/67704
-    template<readable _Tp>
-      struct __iter_common_ref
-      : common_reference<iter_reference_t<_Tp>, iter_value_t<_Tp>&>
-      { };
-  } // namespace __detail
-
-  template<typename _Tp>
+  template<readable _Tp>
     using iter_common_reference_t
-      = typename __detail::__iter_common_ref<_Tp>::type;
+      = common_reference_t<iter_reference_t<_Tp>, iter_value_t<_Tp>&>;
 
   /// Requirements for writing a value into an iterator's referenced object.
   template<typename _Out, typename _Tp>
@@ -663,24 +632,10 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       && strict_weak_order<_Fn&, iter_common_reference_t<_I1>,
 			   iter_common_reference_t<_I2>>;
 
-  namespace __detail
-  {
-    // FIXME: needed due to PR c++/67704
-    template<typename _Fn, typename... _Is>
-      struct __indirect_result
-      { };
-
-    template<typename _Fn, typename... _Is>
-      requires (readable<_Is> && ...)
-	&& invocable<_Fn, iter_reference_t<_Is>...>
-      struct __indirect_result<_Fn, _Is...>
-      : invoke_result<_Fn, iter_reference_t<_Is>...>
-      { };
-  } // namespace __detail
-
   template<typename _Fn, typename... _Is>
-    using indirect_result_t = typename
-      __detail::__indirect_result<_Fn, _Is...>::type;
+    requires (readable<_Is> && ...)
+      && invocable<_Fn, iter_reference_t<_Is>...>
+    using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>;
 
   /// [projected], projected
   template<readable _Iter, indirectly_regular_unary_invocable<_Iter> _Proj>
diff --git a/libstdc++-v3/testsuite/24_iterators/aliases.cc b/libstdc++-v3/testsuite/24_iterators/aliases.cc
new file mode 100644
index 00000000000..29bb56ec0d3
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/aliases.cc
@@ -0,0 +1,61 @@ 
+// Copyright (C) 2020 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 <iterator>
+
+template<typename T>
+struct Dereferenceable { T operator*(); };
+
+template<typename T>
+  concept has_iter_reference
+    = requires { typename std::iter_reference_t<T>; };
+
+template<typename T, typename U>
+  concept is_iter_reference_for
+    = has_iter_reference<U> && std::same_as<T, std::iter_reference_t<U>>;
+
+static_assert(!has_iter_reference<Dereferenceable<void>>);
+static_assert(is_iter_reference_for<int, Dereferenceable<int>>);
+static_assert(is_iter_reference_for<int&, Dereferenceable<int&>>);
+static_assert(is_iter_reference_for<int&&, Dereferenceable<int&&>>);
+static_assert(is_iter_reference_for<int&, int*>);
+static_assert(is_iter_reference_for<const int&, const int*>);
+
+template<typename T>
+  concept has_iter_rvalue_reference
+    = requires { typename std::iter_rvalue_reference_t<T>; };
+
+template<typename T, typename U>
+  concept is_iter_rvalue_reference_for
+    = has_iter_rvalue_reference<U>
+    && std::same_as<T, std::iter_rvalue_reference_t<U>>;
+
+static_assert(!has_iter_rvalue_reference<Dereferenceable<void>>);
+static_assert(is_iter_rvalue_reference_for<int, Dereferenceable<int>>);
+static_assert(is_iter_rvalue_reference_for<int&&, Dereferenceable<int&>>);
+static_assert(is_iter_rvalue_reference_for<int&&, Dereferenceable<int&&>>);
+static_assert(is_iter_rvalue_reference_for<int&&, int*>);
+static_assert(is_iter_rvalue_reference_for<const int&&, const int*>);
+
+// These functions should be found by ADL. std::move is not applied to result.
+long iter_move(Dereferenceable<short>);
+long& iter_move(Dereferenceable<short&&>);
+static_assert(is_iter_rvalue_reference_for<long, Dereferenceable<short>>);
+static_assert(is_iter_rvalue_reference_for<long&, Dereferenceable<short&&>>);