]> gcc.gnu.org Git - gcc.git/blobdiff - libstdc++-v3/include/std/ranges
libstdc++: Some minor <ranges> cleanups
[gcc.git] / libstdc++-v3 / include / std / ranges
index 3e71ecb32b77fcfb8b024a7c427d3014c293fc9a..fb815c48f993c02d54e4c3716e1bfb9621db08b0 100644 (file)
@@ -3116,7 +3116,6 @@ namespace views::__adaptor
 
          _Parent* _M_parent = nullptr;
 
-         // XXX: _M_current is present only if "V models forward_range"
          [[no_unique_address]]
            __detail::__maybe_present_t<forward_range<_Vp>,
                                        iterator_t<_Base>> _M_current;
@@ -3370,7 +3369,6 @@ namespace views::__adaptor
 
       _Vp _M_base = _Vp();
       _Pattern _M_pattern = _Pattern();
-      // XXX: _M_current is "present only if !forward_range<V>"
       [[no_unique_address]]
        __detail::__maybe_present_t<!forward_range<_Vp>,
          __detail::__non_propagating_cache<iterator_t<_Vp>>> _M_current;
@@ -3725,16 +3723,6 @@ namespace views::__adaptor
        : _M_base(std::move(__r))
       { }
 
-      /* XXX: LWG 3280 didn't remove this constructor, but I think it should?
-      template<viewable_range _Range>
-       requires (!common_range<_Range>)
-         && constructible_from<_Vp, views::all_t<_Range>>
-       constexpr explicit
-       common_view(_Range&& __r)
-         : _M_base(views::all(std::forward<_Range>(__r)))
-       { }
-      */
-
       constexpr _Vp
       base() const& requires copy_constructible<_Vp>
       { return _M_base; }
@@ -4115,14 +4103,14 @@ namespace views::__adaptor
          _Iterator() requires default_initializable<iterator_t<_Base>> = default;
 
          constexpr explicit
-         _Iterator(iterator_t<_Base> current)
-           : _M_current(std::move(current))
+         _Iterator(iterator_t<_Base> __current)
+           : _M_current(std::move(__current))
          { }
 
          constexpr
-         _Iterator(_Iterator<!_Const> i)
+         _Iterator(_Iterator<!_Const> __i)
            requires _Const && convertible_to<iterator_t<_Vp>, iterator_t<_Base>>
-           : _M_current(std::move(i._M_current))
+           : _M_current(std::move(__i._M_current))
          { }
 
          constexpr const iterator_t<_Base>&
@@ -4352,6 +4340,448 @@ namespace views::__adaptor
     inline constexpr auto values = elements<1>;
   } // namespace views
 
+#if __cplusplus > 202002L
+  namespace __detail
+  {
+    template<typename... _Rs>
+      concept __zip_is_common = (sizeof...(_Rs) == 1 && (common_range<_Rs> && ...))
+       || (!(bidirectional_range<_Rs> && ...) && (common_range<_Rs> && ...))
+       || ((random_access_range<_Rs> && ...) && (sized_range<_Rs> && ...));
+
+    template<typename... _Ts>
+      struct __tuple_or_pair
+      { using type = std::tuple<_Ts...>; };
+
+    template<typename _Tp, typename _Up>
+      struct __tuple_or_pair<_Tp, _Up>
+      { using type = pair<_Tp, _Up>; };
+
+    template<typename... _Ts>
+      using __tuple_or_pair_t = typename __tuple_or_pair<_Ts...>::type;
+
+    template<typename _Fp, typename _Tuple>
+      constexpr auto
+      __tuple_transform(_Fp&& __f, _Tuple&& __tuple)
+      {
+       return std::apply([&]<typename... _Ts>(_Ts&&... __elts) {
+         return __tuple_or_pair_t<invoke_result_t<_Fp&, _Ts>...>
+           (std::__invoke(__f, std::forward<_Ts>(__elts))...);
+       }, std::forward<_Tuple>(__tuple));
+      }
+
+    template<typename _Fp, typename _Tuple>
+      constexpr void
+      __tuple_for_each(_Fp&& __f, _Tuple&& __tuple)
+      {
+       std::apply([&]<typename... _Ts>(_Ts&&... __elts) {
+         (std::__invoke(__f, std::forward<_Ts>(__elts)), ...);
+       }, std::forward<_Tuple>(__tuple));
+      }
+  } // namespace __detail
+
+  template<input_range... _Vs>
+    requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0)
+  class zip_view : public view_interface<zip_view<_Vs...>>
+  {
+    tuple<_Vs...> _M_views;
+
+    template<bool> class _Iterator;
+    template<bool> class _Sentinel;
+
+  public:
+    zip_view() = default;
+
+    constexpr explicit
+    zip_view(_Vs... __views)
+      : _M_views(std::move(__views)...)
+    { }
+
+    constexpr auto
+    begin() requires (!(__detail::__simple_view<_Vs> && ...))
+    { return _Iterator<false>(__detail::__tuple_transform(ranges::begin, _M_views)); }
+
+    constexpr auto
+    begin() const requires (range<const _Vs> && ...)
+    { return _Iterator<true>(__detail::__tuple_transform(ranges::begin, _M_views)); }
+
+    constexpr auto
+    end() requires (!(__detail::__simple_view<_Vs> && ...))
+    {
+      if constexpr (!__detail::__zip_is_common<_Vs...>)
+        return _Sentinel<false>(__detail::__tuple_transform(ranges::end, _M_views));
+      else if constexpr ((random_access_range<_Vs> && ...))
+        return begin() + iter_difference_t<_Iterator<false>>(size());
+      else
+        return _Iterator<false>(__detail::__tuple_transform(ranges::end, _M_views));
+    }
+
+    constexpr auto
+    end() const requires (range<const _Vs> && ...)
+    {
+      if constexpr (!__detail::__zip_is_common<const _Vs...>)
+        return _Sentinel<true>(__detail::__tuple_transform(ranges::end, _M_views));
+      else if constexpr ((random_access_range<const _Vs> && ...))
+        return begin() + iter_difference_t<_Iterator<true>>(size());
+      else
+        return _Iterator<true>(__detail::__tuple_transform(ranges::end, _M_views));
+    }
+
+    constexpr auto
+    size() requires (sized_range<_Vs> && ...)
+    {
+      return std::apply([](auto... sizes) {
+       using _CT = __detail::__make_unsigned_like_t<common_type_t<decltype(sizes)...>>;
+       return ranges::min({_CT(sizes)...});
+      }, __detail::__tuple_transform(ranges::size, _M_views));
+    }
+
+    constexpr auto
+    size() const requires (sized_range<const _Vs> && ...)
+    {
+      return std::apply([](auto... sizes) {
+       using _CT = __detail::__make_unsigned_like_t<common_type_t<decltype(sizes)...>>;
+       return ranges::min({_CT(sizes)...});
+      }, __detail::__tuple_transform(ranges::size, _M_views));
+    }
+  };
+
+  template<typename... _Rs>
+    zip_view(_Rs&&...) -> zip_view<views::all_t<_Rs>...>;
+
+  template<typename... _Views>
+    inline constexpr bool enable_borrowed_range<zip_view<_Views...>>
+      = (enable_borrowed_range<_Views> && ...);
+
+  namespace __detail
+  {
+    template<bool _Const, typename... _Vs>
+      concept __all_random_access
+       = (random_access_range<__maybe_const_t<_Const, _Vs>> && ...);
+
+    template<bool _Const, typename... _Vs>
+      concept __all_bidirectional
+       = (bidirectional_range<__maybe_const_t<_Const, _Vs>> && ...);
+
+    template<bool _Const, typename... _Vs>
+      concept __all_forward
+       = (forward_range<__maybe_const_t<_Const, _Vs>> && ...);
+
+    template<bool _Const, typename... _Views>
+      struct __zip_view_iter_cat
+      { };
+
+    template<bool _Const, typename... _Views>
+      requires __all_forward<_Const, _Views...>
+      struct __zip_view_iter_cat<_Const, _Views...>
+      { using iterator_category = input_iterator_tag; };
+  } // namespace __detail
+
+  template<input_range... _Vs>
+    requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0)
+  template<bool _Const>
+  class zip_view<_Vs...>::_Iterator
+    : public __detail::__zip_view_iter_cat<_Const, _Vs...>
+  {
+    __detail::__tuple_or_pair_t<iterator_t<__detail::__maybe_const_t<_Const, _Vs>>...> _M_current;
+
+    constexpr explicit
+    _Iterator(decltype(_M_current) __current)
+      : _M_current(std::move(__current))
+    { }
+
+    static auto
+    _S_iter_concept()
+    {
+      if constexpr (__detail::__all_random_access<_Const, _Vs...>)
+       return random_access_iterator_tag{};
+      else if constexpr (__detail::__all_bidirectional<_Const, _Vs...>)
+       return bidirectional_iterator_tag{};
+      else if constexpr (__detail::__all_forward<_Const, _Vs...>)
+       return forward_iterator_tag{};
+      else
+       return input_iterator_tag{};
+    }
+
+  public:
+    // iterator_category defined in __zip_view_iter_cat
+    using iterator_concept = decltype(_S_iter_concept());
+    using value_type
+      = __detail::__tuple_or_pair_t<range_value_t<__detail::__maybe_const_t<_Const, _Vs>>...>;
+    using difference_type
+      = common_type_t<range_difference_t<__detail::__maybe_const_t<_Const, _Vs>>...>;
+
+    _Iterator() = default;
+
+    constexpr
+    _Iterator(_Iterator<!_Const> __i)
+      requires _Const
+       && (convertible_to<iterator_t<_Vs>,
+                          iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...)
+      : _M_current(std::move(__i._M_current))
+    { }
+
+    constexpr auto
+    operator*() const
+    {
+      auto __f = [](auto& __i) -> decltype(auto) {
+       return *__i;
+      };
+      return __detail::__tuple_transform(__f, _M_current);
+    }
+
+    constexpr _Iterator&
+    operator++()
+    {
+      __detail::__tuple_for_each([](auto& __i) { ++__i; }, _M_current);
+      return *this;
+    }
+
+    constexpr void
+    operator++(int)
+    { ++*this; }
+
+    constexpr _Iterator
+    operator++(int)
+      requires __detail::__all_forward<_Const, _Vs...>
+    {
+      auto __tmp = *this;
+      ++*this;
+      return __tmp;
+    }
+
+    constexpr _Iterator&
+    operator--()
+      requires __detail::__all_bidirectional<_Const, _Vs...>
+    {
+      __detail::__tuple_for_each([](auto& __i) { --__i; }, _M_current);
+      return *this;
+    }
+
+    constexpr _Iterator
+    operator--(int)
+      requires __detail::__all_bidirectional<_Const, _Vs...>
+    {
+      auto __tmp = *this;
+      --*this;
+      return __tmp;
+    }
+
+    constexpr _Iterator&
+    operator+=(difference_type __x)
+      requires __detail::__all_random_access<_Const, _Vs...>
+    {
+      auto __f = [&]<typename _It>(_It& __i) {
+       __i += iter_difference_t<_It>(__x);
+      };
+      __detail::__tuple_for_each(__f, _M_current);
+      return *this;
+    }
+
+    constexpr _Iterator&
+    operator-=(difference_type __x)
+      requires __detail::__all_random_access<_Const, _Vs...>
+    {
+      auto __f = [&]<typename _It>(_It& __i) {
+       __i -= iter_difference_t<_It>(__x);
+      };
+      __detail::__tuple_for_each(__f, _M_current);
+      return *this;
+    }
+
+    constexpr auto
+    operator[](difference_type __n) const
+      requires __detail::__all_random_access<_Const, _Vs...>
+    {
+      auto __f = [&]<typename _It>(_It& __i) -> decltype(auto) {
+       return __i[iter_difference_t<_It>(__n)];
+      };
+      return __detail::__tuple_transform(__f, _M_current);
+    }
+
+    friend constexpr bool
+    operator==(const _Iterator& __x, const _Iterator& __y)
+      requires (equality_comparable<iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...)
+    {
+      if constexpr (__detail::__all_bidirectional<_Const, _Vs...>)
+       return __x._M_current == __y._M_current;
+      else
+       return [&]<size_t... _Is>(index_sequence<_Is...>) {
+         return ((std::get<_Is>(__x._M_current) == std::get<_Is>(__y._M_current)) || ...);
+       }(make_index_sequence<sizeof...(_Vs)>{});
+    }
+
+    friend constexpr bool
+    operator<(const _Iterator& __x, const _Iterator& __y)
+      requires __detail::__all_random_access<_Const, _Vs...>
+    { return __x._M_current < __y._M_current; }
+
+    friend constexpr bool
+    operator>(const _Iterator& __x, const _Iterator& __y)
+      requires __detail::__all_random_access<_Const, _Vs...>
+    { return __y < __x; }
+
+    friend constexpr bool
+    operator<=(const _Iterator& __x, const _Iterator& __y)
+      requires __detail::__all_random_access<_Const, _Vs...>
+    { return !(__y < __x); }
+
+    friend constexpr bool
+    operator>=(const _Iterator& __x, const _Iterator& __y)
+      requires __detail::__all_random_access<_Const, _Vs...>
+    { return !(__x < __y); }
+
+    friend constexpr auto
+    operator<=>(const _Iterator& __x, const _Iterator& __y)
+      requires __detail::__all_random_access<_Const, _Vs...>
+       && (three_way_comparable<iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...)
+    { return __x._M_current <=> __y._M_current; }
+
+    friend constexpr _Iterator
+    operator+(const _Iterator& __i, difference_type __n)
+      requires __detail::__all_random_access<_Const, _Vs...>
+    {
+      auto __r = __i;
+      __r += __n;
+      return __r;
+    }
+
+    friend constexpr _Iterator
+    operator+(difference_type __n, const _Iterator& __i)
+      requires __detail::__all_random_access<_Const, _Vs...>
+    {
+      auto __r = __i;
+      __r += __n;
+      return __r;
+    }
+
+    friend constexpr _Iterator
+    operator-(const _Iterator& __i, difference_type __n)
+      requires __detail::__all_random_access<_Const, _Vs...>
+    {
+      auto __r = __i;
+      __r -= __n;
+      return __r;
+    }
+
+    friend constexpr difference_type
+    operator-(const _Iterator& __x, const _Iterator& __y)
+      requires (sized_sentinel_for<iterator_t<__detail::__maybe_const_t<_Const, _Vs>>,
+                                  iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...)
+    {
+      return [&]<size_t... _Is>(index_sequence<_Is...>) {
+       return ranges::min({difference_type(std::get<_Is>(__x._M_current)
+                                           - std::get<_Is>(__y._M_current))...},
+                          ranges::less{},
+                          [](difference_type __i) -> make_unsigned_t<difference_type> {
+                            return __i < 0 ? -__i : __i;
+                          });
+      }(make_index_sequence<sizeof...(_Vs)>{});
+    }
+
+    friend constexpr auto
+    iter_move(const _Iterator& __i)
+    { return __detail::__tuple_transform(ranges::iter_move, __i._M_current); }
+
+    friend constexpr void
+    iter_swap(const _Iterator& __l, const _Iterator& __r)
+      requires (indirectly_swappable<iterator_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...)
+    {
+      [&]<size_t... _Is>(index_sequence<_Is...>) {
+       (ranges::iter_swap(std::get<_Is>(__l._M_current), std::get<_Is>(__r._M_current)), ...);
+      }(make_index_sequence<sizeof...(_Vs)>{});
+    }
+
+    friend class zip_view;
+  };
+
+  template<input_range... _Vs>
+    requires (view<_Vs> && ...) && (sizeof...(_Vs) > 0)
+  template<bool _Const>
+  class zip_view<_Vs...>::_Sentinel
+  {
+    __detail::__tuple_or_pair_t<sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>...> _M_end;
+
+    constexpr explicit
+    _Sentinel(decltype(_M_end) __end)
+      : _M_end(__end)
+    { }
+
+    friend class zip_view;
+
+  public:
+    _Sentinel() = default;
+
+    constexpr
+    _Sentinel(_Sentinel<!_Const> __i)
+      requires _Const
+       && (convertible_to<sentinel_t<_Vs>,
+                          sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>> && ...)
+      : _M_end(std::move(__i._M_end))
+    { }
+
+    template<bool _OtherConst>
+      requires (sentinel_for<sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>,
+                            iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...)
+    friend constexpr bool
+    operator==(const _Iterator<_OtherConst>& __x, const _Sentinel& __y)
+    {
+      return [&]<size_t... _Is>(index_sequence<_Is...>) {
+       return ((std::get<_Is>(__x._M_current) == std::get<_Is>(__y._M_end)) || ...);
+      }(make_index_sequence<sizeof...(_Vs)>{});
+    }
+
+    template<bool _OtherConst>
+      requires (sized_sentinel_for<sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>,
+                                  iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...)
+    friend constexpr auto
+    operator-(const _Iterator<_OtherConst>& __x, const _Sentinel& __y)
+    {
+      using _Ret
+       = common_type_t<range_difference_t<__detail::__maybe_const_t<_OtherConst, _Vs>>...>;
+      return [&]<size_t... _Is>(index_sequence<_Is...>) {
+       return ranges::min({_Ret(std::get<_Is>(__x._M_current) - std::get<_Is>(__y._M_end))...},
+                          ranges::less{},
+                          [](_Ret __i) -> make_unsigned_t<_Ret> {
+                            return __i < 0 ? -__i : __i;
+                          });
+      }(make_index_sequence<sizeof...(_Vs)>{});
+    }
+
+    template<bool _OtherConst>
+      requires (sized_sentinel_for<sentinel_t<__detail::__maybe_const_t<_Const, _Vs>>,
+                                  iterator_t<__detail::__maybe_const_t<_OtherConst, _Vs>>> && ...)
+    friend constexpr auto
+    operator-(const _Sentinel& __y, const _Iterator<_OtherConst>& __x)
+    { return -(__x - __y); }
+  };
+
+  namespace views
+  {
+    namespace __detail
+    {
+      template<typename... _Ts>
+       concept __can_zip_view
+         = requires { zip_view<all_t<_Ts>...>(std::declval<_Ts>()...); };
+    }
+
+    struct _Zip
+    {
+      template<typename... _Ts>
+       requires (sizeof...(_Ts) == 0 || __detail::__can_zip_view<_Ts...>)
+       [[nodiscard]]
+       constexpr auto
+       operator()(_Ts&&... __ts) const
+       {
+         if constexpr (sizeof...(_Ts) == 0)
+           return views::empty<tuple<>>;
+         else
+           return zip_view<all_t<_Ts>...>(std::forward<_Ts>(__ts)...);
+       }
+    };
+
+    inline constexpr _Zip zip;
+  }
+#endif // C++23
 } // namespace ranges
 
   namespace views = ranges::views;
This page took 0.033405 seconds and 5 git commands to generate.