This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 3/3] libstdc++: Implement C++20 range adaptors


On 18/02/20 21:11 +0100, Stephan Bergmann wrote:
On 18/02/2020 12:56, Jonathan Wakely wrote:
Does this solve the problem, and work with both compilers?

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index b9ac528fdff..481ba75ee5e 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1102,6 +1102,9 @@ namespace views
          }
       };

+    template<typename _Callable>
+      _RangeAdaptor(_Callable) -> _RangeAdaptor<_Callable>;
+
     template<typename _Callable>
       struct _RangeAdaptorClosure : public _RangeAdaptor<_Callable>
       {


With this deduction guide CTAD should work, without having to consider
the constraints on the constructors.

Yes, that indeed compiles with both GCC and Clang.

Fixed with this patch, which also introduces some new typedefs to
avoid having to evaluate the iterator_t alias template again and
again.

Tested powerpc64le-linux, committed to master.

There's still something not quite right, because this compiles fine
with GCC but not with Clang:

#include <ranges>
int main()
{
  int a[1] = { 2 };
  auto f = a | std::views::filter([](auto&&){return true;});
  return *std::ranges::begin(f);
}

commit a5b213dda50aca90637979f13da2eb377eff9930
Author: Jonathan Wakely <jwakely@redhat.com>
Date:   Tue Feb 18 23:22:25 2020 +0000

    libstdc++: Fix compilation of <ranges> with Clang (PR 93818)
    
            PR libstdc++/93818
            * include/std/ranges (_RangeAdaptor): Add deduction guide.
            (filter_view::_Iterator): Add alias _Vp_iter and use in place of
            iterator_t<_Vp>.
            (filter_view::_Iterator::_S_iter_cat()): Add 'typename'.
            (transform_view::_Iterator): Add alias _Base_iter and use in place of
            iterator_t<_Base>.
            (transform_view::_Iterator::_S_iter_cat()): Add 'typename'.
            (join_view::_Iterator): Add _Outer_iter and _Inner_iter aliases.
            (join_view::_Iterator::_S_iter_cat()): Add 'typename'.
            (split_view::_InnerIter::_S_iter_cat()): Likewise.

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index b9ac528fdff..e6bdac315c0 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -1102,6 +1102,9 @@ namespace views
 	  }
       };
 
+    template<typename _Callable>
+      _RangeAdaptor(_Callable) -> _RangeAdaptor<_Callable>;
+
     template<typename _Callable>
       struct _RangeAdaptorClosure : public _RangeAdaptor<_Callable>
       {
@@ -1325,7 +1328,7 @@ namespace views
 	static constexpr auto
 	_S_iter_cat()
 	{
-	  using _Cat = iterator_traits<iterator_t<_Vp>>::iterator_category;
+	  using _Cat = typename iterator_traits<_Vp_iter>::iterator_category;
 	  if constexpr (derived_from<_Cat, bidirectional_iterator_tag>)
 	    return bidirectional_iterator_tag{};
 	  else if constexpr (derived_from<_Cat, forward_iterator_tag>)
@@ -1336,7 +1339,9 @@ namespace views
 
 	friend filter_view;
 
-	iterator_t<_Vp> _M_current = iterator_t<_Vp>();
+	using _Vp_iter = iterator_t<_Vp>;
+
+	_Vp_iter _M_current = _Vp_iter();
 	filter_view* _M_parent = nullptr;
 
       public:
@@ -1348,17 +1353,17 @@ namespace views
 	_Iterator() = default;
 
 	constexpr
-	_Iterator(filter_view& __parent, iterator_t<_Vp> __current)
+	_Iterator(filter_view& __parent, _Vp_iter __current)
 	  : _M_current(std::move(__current)),
 	    _M_parent(std::__addressof(__parent))
 	{ }
 
-	constexpr iterator_t<_Vp>
+	constexpr _Vp_iter
 	base() const &
-	  requires copyable<iterator_t<_Vp>>
+	  requires copyable<_Vp_iter>
 	{ return _M_current; }
 
-	constexpr iterator_t<_Vp>
+	constexpr _Vp_iter
 	base() &&
 	{ return std::move(_M_current); }
 
@@ -1366,10 +1371,10 @@ namespace views
 	operator*() const
 	{ return *_M_current; }
 
-	constexpr iterator_t<_Vp>
+	constexpr _Vp_iter
 	operator->() const
-	  requires __detail::__has_arrow<iterator_t<_Vp>>
-	    && copyable<iterator_t<_Vp>>
+	  requires __detail::__has_arrow<_Vp_iter>
+	    && copyable<_Vp_iter>
 	{ return _M_current; }
 
 	constexpr _Iterator&
@@ -1412,7 +1417,7 @@ namespace views
 
 	friend constexpr bool
 	operator==(const _Iterator& __x, const _Iterator& __y)
-	  requires equality_comparable<iterator_t<_Vp>>
+	  requires equality_comparable<_Vp_iter>
 	{ return __x._M_current == __y._M_current; }
 
 	friend constexpr range_rvalue_reference_t<_Vp>
@@ -1423,7 +1428,7 @@ namespace views
 	friend constexpr void
 	iter_swap(const _Iterator& __x, const _Iterator& __y)
 	  noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current)))
-	  requires indirectly_swappable<iterator_t<_Vp>>
+	  requires indirectly_swappable<_Vp_iter>
 	{ ranges::iter_swap(__x._M_current, __y._M_current); }
       };
 
@@ -1548,7 +1553,8 @@ namespace views
 	  static constexpr auto
 	  _S_iter_cat()
 	  {
-	    using _Cat = iterator_traits<iterator_t<_Base>>::iterator_category;
+	    using _Cat
+              = typename iterator_traits<_Base_iter>::iterator_category;
 	    if constexpr (derived_from<_Cat, contiguous_iterator_tag>)
 	      return random_access_iterator_tag{};
 	    else
@@ -1566,7 +1572,9 @@ namespace views
 	      return *__i;
 	  }
 
-	  iterator_t<_Base> _M_current = iterator_t<_Base>();
+	  using _Base_iter = iterator_t<_Base>;
+
+	  _Base_iter _M_current = _Base_iter();
 	  _Parent* _M_parent = nullptr;
 
 	public:
@@ -1579,7 +1587,7 @@ namespace views
 	  _Iterator() = default;
 
 	  constexpr
-	  _Iterator(_Parent& __parent, iterator_t<_Base> __current)
+	  _Iterator(_Parent& __parent, _Base_iter __current)
 	    : _M_current(std::move(__current)),
 	      _M_parent(std::__addressof(__parent))
 	  { }
@@ -1587,16 +1595,16 @@ namespace views
 	  constexpr
 	  _Iterator(_Iterator<!_Const> __i)
 	    requires _Const
-	      && convertible_to<iterator_t<_Vp>, iterator_t<_Base>>
+	      && convertible_to<iterator_t<_Vp>, _Base_iter>
 	    : _M_current(std::move(__i._M_current)), _M_parent(__i._M_parent)
 	  { }
 
-	  constexpr iterator_t<_Base>
+	  constexpr _Base_iter
 	  base() const &
-	    requires copyable<iterator_t<_Base>>
+	    requires copyable<_Base_iter>
 	  { return _M_current; }
 
-	  constexpr iterator_t<_Base>
+	  constexpr _Base_iter
 	  base() &&
 	  { return std::move(_M_current); }
 
@@ -1659,7 +1667,7 @@ namespace views
 
 	  friend constexpr bool
 	  operator==(const _Iterator& __x, const _Iterator& __y)
-	    requires equality_comparable<iterator_t<_Base>>
+	    requires equality_comparable<_Base_iter>
 	  { return __x._M_current == __y._M_current; }
 
 	  friend constexpr bool
@@ -1686,7 +1694,7 @@ namespace views
 	  friend constexpr auto
 	  operator<=>(const _Iterator& __x, const _Iterator& __y)
 	    requires random_access_range<_Base>
-	      && three_way_comparable<iterator_t<_Base>>
+	      && three_way_comparable<_Base_iter>
 	  { return __x._M_current <=> __y._M_current; }
 #endif
 
@@ -1717,7 +1725,7 @@ namespace views
 	  friend constexpr void
 	  iter_swap(const _Iterator& __x, const _Iterator& __y)
 	    noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current)))
-	    requires indirectly_swappable<iterator_t<_Base>>
+	    requires indirectly_swappable<_Base_iter>
 	  { return ranges::iter_swap(__x._M_current, __y._M_current); }
 
 	  friend _Sentinel<_Const>;
@@ -2271,7 +2279,7 @@ namespace views
 	      }
 
 	    if constexpr (_S_ref_is_glvalue)
-	      _M_inner = iterator_t<range_reference_t<_Base>>();
+	      _M_inner = _Inner_iter();
 	  }
 
 	  static constexpr auto
@@ -2293,10 +2301,9 @@ namespace views
 	  _S_iter_cat()
 	  {
 	    using _OuterCat
-	      = iterator_traits<iterator_t<_Base>>::iterator_category;
+	      = typename iterator_traits<_Outer_iter>::iterator_category;
 	    using _InnerCat
-	      = iterator_traits<iterator_t<range_reference_t<_Base>>>
-		 ::iterator_category;
+	      = typename iterator_traits<_Inner_iter>::iterator_category;
 	    if constexpr (_S_ref_is_glvalue
 			  && derived_from<_OuterCat, bidirectional_iterator_tag>
 			  && derived_from<_InnerCat, bidirectional_iterator_tag>)
@@ -2312,9 +2319,11 @@ namespace views
 	      return output_iterator_tag{};
 	  }
 
-	  iterator_t<_Base> _M_outer = iterator_t<_Base>();
-	  iterator_t<range_reference_t<_Base>> _M_inner
-	    = iterator_t<range_reference_t<_Base>>();
+	  using _Outer_iter = iterator_t<_Base>;
+	  using _Inner_iter = iterator_t<range_reference_t<_Base>>;
+
+	  _Outer_iter _M_outer = _Outer_iter();
+	  _Inner_iter _M_inner = _Inner_iter();
 	  _Parent* _M_parent = nullptr;
 
 	public:
@@ -2330,7 +2339,7 @@ namespace views
 	  // XXX: had to change the type of __outer from iterator_t<_Vp> to
 	  // iterator_t<_Base> here, a possible defect in the spec?
 	  constexpr
-	  _Iterator(_Parent& __parent, iterator_t<_Base> __outer)
+	  _Iterator(_Parent& __parent, _Outer_iter __outer)
 	    : _M_outer(std::move(__outer)),
 	      _M_parent(std::__addressof(__parent))
 	  { _M_satisfy(); }
@@ -2338,9 +2347,8 @@ namespace views
 	  constexpr
 	  _Iterator(_Iterator<!_Const> __i)
 	    requires _Const
-	      && convertible_to<iterator_t<_Vp>, iterator_t<_Base>>
-	      && convertible_to<iterator_t<_InnerRange>,
-				iterator_t<range_reference_t<_Base>>>
+	      && convertible_to<iterator_t<_Vp>, _Outer_iter>
+	      && convertible_to<iterator_t<_InnerRange>, _Inner_iter>
 	    : _M_outer(std::move(__i._M_outer)), _M_inner(__i._M_inner),
 	      _M_parent(__i._M_parent)
 	  { }
@@ -2349,10 +2357,10 @@ namespace views
 	  operator*() const
 	  { return *_M_inner; }
 
-	  constexpr iterator_t<_Base>
+	  constexpr _Outer_iter
 	  operator->() const
-	    requires __detail::__has_arrow<iterator_t<_Base>>
-	      && copyable<iterator_t<_Base>>
+	    requires __detail::__has_arrow<_Outer_iter>
+	      && copyable<_Outer_iter>
 	  { return _M_inner; }
 
 	  constexpr _Iterator&
@@ -2412,8 +2420,8 @@ namespace views
 	  friend constexpr bool
 	  operator==(const _Iterator& __x, const _Iterator& __y)
 	    requires _S_ref_is_glvalue
-	      && equality_comparable<iterator_t<_Base>>
-	      && equality_comparable<iterator_t<range_reference_t<_Base>>>
+	      && equality_comparable<_Outer_iter>
+	      && equality_comparable<_Inner_iter>
 	  {
 	    return (__x._M_outer == __y._M_outer
 		    && __x._M_inner == __y._M_inner);
@@ -2764,7 +2772,8 @@ namespace views
 	  static constexpr auto
 	  _S_iter_cat()
 	  {
-	    using _Cat = iterator_traits<iterator_t<_Base>>::iterator_category;
+	    using _Cat
+              = typename iterator_traits<iterator_t<_Base>>::iterator_category;
 	    if constexpr (derived_from<_Cat, forward_iterator_tag>)
 	      return forward_iterator_tag{};
 	    else
@@ -2786,7 +2795,8 @@ namespace views
 	  bool _M_incremented = false;
 
 	public:
-	  using iterator_concept = typename _OuterIter<_Const>::iterator_concept;
+	  using iterator_concept
+	    = typename _OuterIter<_Const>::iterator_concept;
 	  using iterator_category = decltype(_S_iter_cat());
 	  using value_type = range_value_t<_Base>;
 	  using difference_type = range_difference_t<_Base>;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]