diff --git a/libcxx/include/__ranges/lazy_split_view.h b/libcxx/include/__ranges/lazy_split_view.h --- a/libcxx/include/__ranges/lazy_split_view.h +++ b/libcxx/include/__ranges/lazy_split_view.h @@ -51,6 +51,9 @@ template struct __require_constant; +template struct __lazy_split_view_outer_iterator; +template struct __lazy_split_view_inner_iterator; + template concept __tiny_range = sized_range<_Range> && @@ -69,8 +72,11 @@ using _MaybeCurrent = _If, __non_propagating_cache>, __empty_cache>; _LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent(); - template struct __outer_iterator; - template struct __inner_iterator; + template friend struct __lazy_split_view_outer_iterator; + template friend struct __lazy_split_view_inner_iterator; + + template using __outer_iterator = __lazy_split_view_outer_iterator<_Const, _View, _Pattern>; + template using __inner_iterator = __lazy_split_view_inner_iterator<_Const, _View, _Pattern>; public: _LIBCPP_HIDE_FROM_ABI @@ -123,305 +129,314 @@ } } -private: +}; - template - struct __outer_iterator_category {}; +template +struct __lazy_split_view_outer_iterator_category {}; - template - struct __outer_iterator_category<_Tp> { - using iterator_category = input_iterator_tag; - }; +template +struct __lazy_split_view_outer_iterator_category<_Tp> { + using iterator_category = input_iterator_tag; +}; - template - struct __outer_iterator : __outer_iterator_category<__maybe_const<_Const, _View>> { - private: - template - friend struct __inner_iterator; - friend __outer_iterator; - - using _Parent = __maybe_const<_Const, lazy_split_view>; - using _Base = __maybe_const<_Const, _View>; - - _Parent* __parent_ = nullptr; - using _MaybeCurrent = _If, iterator_t<_Base>, __empty_cache>; - _LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent(); - bool __trailing_empty_ = false; - - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI - constexpr auto& __current() noexcept { - if constexpr (forward_range<_View>) { - return __current_; - } else { - return *__parent_->__current_; - } - } +template +struct __lazy_split_view_outer_iterator : __lazy_split_view_outer_iterator_category<__maybe_const<_Const, _View>> { +private: + template + friend struct __lazy_split_view_inner_iterator; + friend __lazy_split_view_outer_iterator; + + using _Parent = __maybe_const<_Const, lazy_split_view<_View, _Pattern>>; + using _Base = __maybe_const<_Const, _View>; + template + using __outer_iterator = __lazy_split_view_outer_iterator<_OtherConst, _View, _Pattern>; + template + using __inner_iterator = __lazy_split_view_inner_iterator<_OtherConst, _View, _Pattern>; + + _Parent* __parent_ = nullptr; + using _MaybeCurrent = _If, iterator_t<_Base>, __empty_cache>; + _LIBCPP_NO_UNIQUE_ADDRESS _MaybeCurrent __current_ = _MaybeCurrent(); + bool __trailing_empty_ = false; - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI - constexpr const auto& __current() const noexcept { - if constexpr (forward_range<_View>) { - return __current_; - } else { - return *__parent_->__current_; - } + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr auto& __current() noexcept { + if constexpr (forward_range<_View>) { + return __current_; + } else { + return *__parent_->__current_; } + } - // Workaround for the GCC issue that doesn't allow calling `__parent_->__base_` from friend functions (because - // `__base_` is private). - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI - constexpr auto& __parent_base() const noexcept { - return __parent_->__base_; + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr const auto& __current() const noexcept { + if constexpr (forward_range<_View>) { + return __current_; + } else { + return *__parent_->__current_; } + } - public: - // using iterator_category = inherited; - using iterator_concept = conditional_t, forward_iterator_tag, input_iterator_tag>; - using difference_type = range_difference_t<_Base>; - - struct value_type : view_interface { - private: - __outer_iterator __i_ = __outer_iterator(); - - public: - _LIBCPP_HIDE_FROM_ABI - value_type() = default; - _LIBCPP_HIDE_FROM_ABI - constexpr explicit value_type(__outer_iterator __i) - : __i_(std::move(__i)) {} - - _LIBCPP_HIDE_FROM_ABI - constexpr __inner_iterator<_Const> begin() const { return __inner_iterator<_Const>{__i_}; } - _LIBCPP_HIDE_FROM_ABI - constexpr default_sentinel_t end() const noexcept { return default_sentinel; } - }; + // Workaround for the GCC issue that doesn't allow calling `__parent_->__base_` from friend functions (because + // `__base_` is private). + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr auto& __parent_base() const noexcept { + return __parent_->__base_; + } - _LIBCPP_HIDE_FROM_ABI - __outer_iterator() = default; +public: + // using iterator_category = inherited; + using iterator_concept = conditional_t, forward_iterator_tag, input_iterator_tag>; + using difference_type = range_difference_t<_Base>; - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __outer_iterator(_Parent& __parent) - requires (!forward_range<_Base>) - : __parent_(std::addressof(__parent)) {} + struct value_type : view_interface { + private: + __lazy_split_view_outer_iterator __i_ = __lazy_split_view_outer_iterator(); + public: _LIBCPP_HIDE_FROM_ABI - constexpr __outer_iterator(_Parent& __parent, iterator_t<_Base> __current) - requires forward_range<_Base> - : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {} - + value_type() = default; _LIBCPP_HIDE_FROM_ABI - constexpr __outer_iterator(__outer_iterator __i) - requires _Const && convertible_to, iterator_t<_Base>> - : __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {} + constexpr explicit value_type(__lazy_split_view_outer_iterator __i) + : __i_(std::move(__i)) {} _LIBCPP_HIDE_FROM_ABI - constexpr value_type operator*() const { return value_type{*this}; } - + constexpr __inner_iterator<_Const> begin() const { + return __inner_iterator<_Const>{__i_}; + } _LIBCPP_HIDE_FROM_ABI - constexpr __outer_iterator& operator++() { - const auto __end = ranges::end(__parent_->__base_); - if (__current() == __end) { - __trailing_empty_ = false; - return *this; - } + constexpr default_sentinel_t end() const noexcept { return default_sentinel; } + }; - const auto [__pbegin, __pend] = ranges::subrange{__parent_->__pattern_}; - if (__pbegin == __pend) { - // Empty pattern: split on every element in the input range - ++__current(); + _LIBCPP_HIDE_FROM_ABI + __lazy_split_view_outer_iterator() = default; - } else if constexpr (__tiny_range<_Pattern>) { - // One-element pattern: we can use `ranges::find`. - __current() = ranges::find(std::move(__current()), __end, *__pbegin); - if (__current() != __end) { - // Make sure we point to after the separator we just found. - ++__current(); - if (__current() == __end) - __trailing_empty_ = true; - } + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __lazy_split_view_outer_iterator(_Parent& __parent) + requires (!forward_range<_Base>) + : __parent_(std::addressof(__parent)) {} - } else { - // General case for n-element pattern. - do { - const auto [__b, __p] = ranges::mismatch(__current(), __end, __pbegin, __pend); - if (__p == __pend) { - __current() = __b; - if (__current() == __end) { - __trailing_empty_ = true; - } - break; // The pattern matched; skip it. - } - } while (++__current() != __end); - } + _LIBCPP_HIDE_FROM_ABI + constexpr __lazy_split_view_outer_iterator(_Parent& __parent, iterator_t<_Base> __current) + requires forward_range<_Base> + : __parent_(std::addressof(__parent)), __current_(std::move(__current)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr __lazy_split_view_outer_iterator(__outer_iterator __i) + requires _Const && convertible_to, iterator_t<_Base>> + : __parent_(__i.__parent_), __current_(std::move(__i.__current_)) {} + + _LIBCPP_HIDE_FROM_ABI + constexpr value_type operator*() const { return value_type{*this}; } + _LIBCPP_HIDE_FROM_ABI + constexpr __lazy_split_view_outer_iterator& operator++() { + const auto __end = ranges::end(__parent_->__base_); + if (__current() == __end) { + __trailing_empty_ = false; return *this; } - _LIBCPP_HIDE_FROM_ABI - constexpr decltype(auto) operator++(int) { - if constexpr (forward_range<_Base>) { - auto __tmp = *this; - ++*this; - return __tmp; - - } else { - ++*this; + const auto [__pbegin, __pend] = ranges::subrange{__parent_->__pattern_}; + if (__pbegin == __pend) { + // Empty pattern: split on every element in the input range + ++__current(); + + } else if constexpr (__tiny_range<_Pattern>) { + // One-element pattern: we can use `ranges::find`. + __current() = ranges::find(std::move(__current()), __end, *__pbegin); + if (__current() != __end) { + // Make sure we point to after the separator we just found. + ++__current(); + if (__current() == __end) + __trailing_empty_ = true; } - } - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __outer_iterator& __x, const __outer_iterator& __y) - requires forward_range<_Base> { - return __x.__current_ == __y.__current_ && __x.__trailing_empty_ == __y.__trailing_empty_; + } else { + // General case for n-element pattern. + do { + const auto [__b, __p] = ranges::mismatch(__current(), __end, __pbegin, __pend); + if (__p == __pend) { + __current() = __b; + if (__current() == __end) { + __trailing_empty_ = true; + } + break; // The pattern matched; skip it. + } + } while (++__current() != __end); } - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __outer_iterator& __x, default_sentinel_t) { - _LIBCPP_ASSERT(__x.__parent_, "Cannot call comparison on a default-constructed iterator."); - return __x.__current() == ranges::end(__x.__parent_base()) && !__x.__trailing_empty_; - } - }; + return *this; + } - template - struct __inner_iterator_category {}; + _LIBCPP_HIDE_FROM_ABI + constexpr decltype(auto) operator++(int) { + if constexpr (forward_range<_Base>) { + auto __tmp = *this; + ++*this; + return __tmp; - template - struct __inner_iterator_category<_Tp> { - using iterator_category = _If< - derived_from>::iterator_category, forward_iterator_tag>, - forward_iterator_tag, - typename iterator_traits>::iterator_category - >; - }; + } else { + ++*this; + } + } - template - struct __inner_iterator : __inner_iterator_category<__maybe_const<_Const, _View>> { - private: - using _Base = __maybe_const<_Const, _View>; - // Workaround for a GCC issue. - static constexpr bool _OuterConst = _Const; - __outer_iterator<_Const> __i_ = __outer_iterator<_OuterConst>(); - bool __incremented_ = false; + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __lazy_split_view_outer_iterator& __x, + const __lazy_split_view_outer_iterator& __y) + requires forward_range<_Base> { + return __x.__current_ == __y.__current_ && __x.__trailing_empty_ == __y.__trailing_empty_; + } - // Note: these private functions are necessary because GCC doesn't allow calls to private members of `__i_` from - // free functions that are friends of `inner-iterator`. + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __lazy_split_view_outer_iterator& __x, default_sentinel_t) { + _LIBCPP_ASSERT(__x.__parent_, "Cannot call comparison on a default-constructed iterator."); + return __x.__current() == ranges::end(__x.__parent_base()) && !__x.__trailing_empty_; + } +}; - _LIBCPP_HIDE_FROM_ABI - constexpr bool __is_done() const { - _LIBCPP_ASSERT(__i_.__parent_, "Cannot call comparison on a default-constructed iterator."); +template +struct __lazy_split_view_inner_iterator_category {}; - auto [__pcur, __pend] = ranges::subrange{__i_.__parent_->__pattern_}; - auto __end = ranges::end(__i_.__parent_->__base_); +template +struct __lazy_split_view_inner_iterator_category<_Tp> { + using iterator_category = _If< + derived_from>::iterator_category, forward_iterator_tag>, + forward_iterator_tag, + typename iterator_traits>::iterator_category + >; +}; - if constexpr (__tiny_range<_Pattern>) { - const auto& __cur = __i_.__current(); - if (__cur == __end) - return true; - if (__pcur == __pend) - return __incremented_; +template +struct __lazy_split_view_inner_iterator : __lazy_split_view_inner_iterator_category<__maybe_const<_Const, _View>> { +private: + using _Base = __maybe_const<_Const, _View>; + // Workaround for a GCC issue. + static constexpr bool _OuterConst = _Const; + template + using __outer_iterator = __lazy_split_view_outer_iterator<_Const, _View, _Pattern>; + __outer_iterator<_Const> __i_ = __outer_iterator<_OuterConst>(); + bool __incremented_ = false; - return *__cur == *__pcur; + // Note: these private functions are necessary because GCC doesn't allow calls to private members of `__i_` from + // free functions that are friends of `inner-iterator`. - } else { - auto __cur = __i_.__current(); - if (__cur == __end) - return true; - if (__pcur == __pend) - return __incremented_; + _LIBCPP_HIDE_FROM_ABI + constexpr bool __is_done() const { + _LIBCPP_ASSERT(__i_.__parent_, "Cannot call comparison on a default-constructed iterator."); - do { - if (*__cur != *__pcur) - return false; - if (++__pcur == __pend) - return true; - } while (++__cur != __end); + auto [__pcur, __pend] = ranges::subrange{__i_.__parent_->__pattern_}; + auto __end = ranges::end(__i_.__parent_->__base_); - return false; - } - } + if constexpr (__tiny_range<_Pattern>) { + const auto& __cur = __i_.__current(); + if (__cur == __end) + return true; + if (__pcur == __pend) + return __incremented_; - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI - constexpr auto& __outer_current() noexcept { - return __i_.__current(); - } + return *__cur == *__pcur; - [[nodiscard]] _LIBCPP_HIDE_FROM_ABI - constexpr const auto& __outer_current() const noexcept { - return __i_.__current(); + } else { + auto __cur = __i_.__current(); + if (__cur == __end) + return true; + if (__pcur == __pend) + return __incremented_; + + do { + if (*__cur != *__pcur) + return false; + if (++__pcur == __pend) + return true; + } while (++__cur != __end); + + return false; } + } - public: - // using iterator_category = inherited; - using iterator_concept = typename __outer_iterator<_Const>::iterator_concept; - using value_type = range_value_t<_Base>; - using difference_type = range_difference_t<_Base>; + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr auto& __outer_current() noexcept { + return __i_.__current(); + } - _LIBCPP_HIDE_FROM_ABI - __inner_iterator() = default; + [[nodiscard]] _LIBCPP_HIDE_FROM_ABI + constexpr const auto& __outer_current() const noexcept { + return __i_.__current(); + } - _LIBCPP_HIDE_FROM_ABI - constexpr explicit __inner_iterator(__outer_iterator<_Const> __i) - : __i_(std::move(__i)) {} +public: + // using iterator_category = inherited; + using iterator_concept = typename __outer_iterator<_Const>::iterator_concept; + using value_type = range_value_t<_Base>; + using difference_type = range_difference_t<_Base>; - _LIBCPP_HIDE_FROM_ABI - constexpr const iterator_t<_Base>& base() const& noexcept { return __i_.__current(); } - _LIBCPP_HIDE_FROM_ABI - constexpr iterator_t<_Base> base() && - requires forward_range<_View> { return std::move(__i_.__current()); } + _LIBCPP_HIDE_FROM_ABI + __lazy_split_view_inner_iterator() = default; - _LIBCPP_HIDE_FROM_ABI - constexpr decltype(auto) operator*() const { return *__i_.__current(); } + _LIBCPP_HIDE_FROM_ABI + constexpr explicit __lazy_split_view_inner_iterator(__outer_iterator<_Const> __i) + : __i_(std::move(__i)) {} - _LIBCPP_HIDE_FROM_ABI - constexpr __inner_iterator& operator++() { - __incremented_ = true; + _LIBCPP_HIDE_FROM_ABI + constexpr const iterator_t<_Base>& base() const& noexcept { return __i_.__current(); } + _LIBCPP_HIDE_FROM_ABI + constexpr iterator_t<_Base> base() && + requires forward_range<_View> { return std::move(__i_.__current()); } - if constexpr (!forward_range<_Base>) { - if constexpr (_Pattern::size() == 0) { - return *this; - } - } + _LIBCPP_HIDE_FROM_ABI + constexpr decltype(auto) operator*() const { return *__i_.__current(); } - ++__i_.__current(); - return *this; - } + _LIBCPP_HIDE_FROM_ABI + constexpr __lazy_split_view_inner_iterator& operator++() { + __incremented_ = true; - _LIBCPP_HIDE_FROM_ABI - constexpr decltype(auto) operator++(int) { - if constexpr (forward_range<_Base>) { - auto __tmp = *this; - ++*this; - return __tmp; - - } else { - ++*this; + if constexpr (!forward_range<_Base>) { + if constexpr (_Pattern::size() == 0) { + return *this; } } - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __inner_iterator& __x, const __inner_iterator& __y) - requires forward_range<_Base> { - return __x.__outer_current() == __y.__outer_current(); - } + ++__i_.__current(); + return *this; + } - _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __inner_iterator& __x, default_sentinel_t) { - return __x.__is_done(); - } + _LIBCPP_HIDE_FROM_ABI + constexpr decltype(auto) operator++(int) { + if constexpr (forward_range<_Base>) { + auto __tmp = *this; + ++*this; + return __tmp; - _LIBCPP_HIDE_FROM_ABI - friend constexpr decltype(auto) iter_move(const __inner_iterator& __i) - noexcept(noexcept(ranges::iter_move(__i.__outer_current()))) { - return ranges::iter_move(__i.__outer_current()); + } else { + ++*this; } + } - _LIBCPP_HIDE_FROM_ABI - friend constexpr void iter_swap(const __inner_iterator& __x, const __inner_iterator& __y) - noexcept(noexcept(ranges::iter_swap(__x.__outer_current(), __y.__outer_current()))) - requires indirectly_swappable> { - ranges::iter_swap(__x.__outer_current(), __y.__outer_current()); - } - }; + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __lazy_split_view_inner_iterator& __x, + const __lazy_split_view_inner_iterator& __y) + requires forward_range<_Base> { + return __x.__outer_current() == __y.__outer_current(); + } + _LIBCPP_HIDE_FROM_ABI + friend constexpr bool operator==(const __lazy_split_view_inner_iterator& __x, default_sentinel_t) { + return __x.__is_done(); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr decltype(auto) iter_move(const __lazy_split_view_inner_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i.__outer_current()))) { + return ranges::iter_move(__i.__outer_current()); + } + + _LIBCPP_HIDE_FROM_ABI + friend constexpr void iter_swap(const __lazy_split_view_inner_iterator& __x, + const __lazy_split_view_inner_iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x.__outer_current(), __y.__outer_current()))) + requires indirectly_swappable> { + ranges::iter_swap(__x.__outer_current(), __y.__outer_current()); + } }; template diff --git a/libcxx/include/__ranges/zip_view.h b/libcxx/include/__ranges/zip_view.h --- a/libcxx/include/__ranges/zip_view.h +++ b/libcxx/include/__ranges/zip_view.h @@ -123,17 +123,20 @@ return __t < 0 ? -__t : __t; } +template class __zip_view_iterator; +template class __zip_view_sentinel; + template requires(view<_Views> && ...) && (sizeof...(_Views) > 0) class zip_view : public view_interface> { _LIBCPP_NO_UNIQUE_ADDRESS tuple<_Views...> __views_; - template - class __iterator; + template + using __iterator = __zip_view_iterator<_Const, _Views...>; - template - class __sentinel; + template + using __sentinel = __zip_view_sentinel<_Const, _Views...>; public: _LIBCPP_HIDE_FROM_ABI @@ -235,22 +238,20 @@ using iterator_category = input_iterator_tag; }; -template - requires(view<_Views> && ...) && (sizeof...(_Views) > 0) -template -class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base<_Const, _Views...> { +template +class __zip_view_iterator : public __zip_view_iterator_category_base<_Const, _Views...> { __tuple_or_pair>...> __current_; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __iterator(__tuple_or_pair>...> __current) + constexpr explicit __zip_view_iterator(__tuple_or_pair>...> __current) : __current_(std::move(__current)) {} - template - friend class zip_view<_Views...>::__iterator; + template + friend class __zip_view_iterator; - template - friend class zip_view<_Views...>::__sentinel; + template + friend class __zip_view_sentinel; friend class zip_view<_Views...>; @@ -260,10 +261,10 @@ using difference_type = common_type_t>...>; _LIBCPP_HIDE_FROM_ABI - __iterator() = default; + __zip_view_iterator() = default; _LIBCPP_HIDE_FROM_ABI - constexpr __iterator(__iterator __i) + constexpr __zip_view_iterator(__zip_view_iterator __i) requires _Const && (convertible_to, iterator_t<__maybe_const<_Const, _Views>>> && ...) : __current_(std::move(__i.__current_)) {} @@ -273,7 +274,7 @@ } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator++() { + constexpr __zip_view_iterator& operator++() { ranges::__tuple_for_each([](auto& __i) { ++__i; }, __current_); return *this; } @@ -282,7 +283,7 @@ constexpr void operator++(int) { ++*this; } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator++(int) + constexpr __zip_view_iterator operator++(int) requires __zip_all_forward<_Const, _Views...> { auto __tmp = *this; ++*this; @@ -290,14 +291,14 @@ } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator--() + constexpr __zip_view_iterator& operator--() requires __zip_all_bidirectional<_Const, _Views...> { ranges::__tuple_for_each([](auto& __i) { --__i; }, __current_); return *this; } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator operator--(int) + constexpr __zip_view_iterator operator--(int) requires __zip_all_bidirectional<_Const, _Views...> { auto __tmp = *this; --*this; @@ -305,14 +306,14 @@ } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator+=(difference_type __x) + constexpr __zip_view_iterator& operator+=(difference_type __x) requires __zip_all_random_access<_Const, _Views...> { ranges::__tuple_for_each([&](_Iter& __i) { __i += iter_difference_t<_Iter>(__x); }, __current_); return *this; } _LIBCPP_HIDE_FROM_ABI - constexpr __iterator& operator-=(difference_type __x) + constexpr __zip_view_iterator& operator-=(difference_type __x) requires __zip_all_random_access<_Const, _Views...> { ranges::__tuple_for_each([&](_Iter& __i) { __i -= iter_difference_t<_Iter>(__x); }, __current_); return *this; @@ -326,7 +327,7 @@ } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator==(const __zip_view_iterator& __x, const __zip_view_iterator& __y) requires(equality_comparable>> && ...) { if constexpr (__zip_all_bidirectional<_Const, _Views...>) { return __x.__current_ == __y.__current_; @@ -336,38 +337,38 @@ } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator<(const __zip_view_iterator& __x, const __zip_view_iterator& __y) requires __zip_all_random_access<_Const, _Views...> { return __x.__current_ < __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator>(const __zip_view_iterator& __x, const __zip_view_iterator& __y) requires __zip_all_random_access<_Const, _Views...> { return __y < __x; } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator<=(const __zip_view_iterator& __x, const __zip_view_iterator& __y) requires __zip_all_random_access<_Const, _Views...> { return !(__y < __x); } _LIBCPP_HIDE_FROM_ABI - friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) + friend constexpr bool operator>=(const __zip_view_iterator& __x, const __zip_view_iterator& __y) requires __zip_all_random_access<_Const, _Views...> { return !(__x < __y); } _LIBCPP_HIDE_FROM_ABI - friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) + friend constexpr auto operator<=>(const __zip_view_iterator& __x, const __zip_view_iterator& __y) requires __zip_all_random_access<_Const, _Views...> && (three_way_comparable>> && ...) { return __x.__current_ <=> __y.__current_; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator+(const __iterator& __i, difference_type __n) + friend constexpr __zip_view_iterator operator+(const __zip_view_iterator& __i, difference_type __n) requires __zip_all_random_access<_Const, _Views...> { auto __r = __i; __r += __n; @@ -375,13 +376,13 @@ } _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator+(difference_type __n, const __iterator& __i) + friend constexpr __zip_view_iterator operator+(difference_type __n, const __zip_view_iterator& __i) requires __zip_all_random_access<_Const, _Views...> { return __i + __n; } _LIBCPP_HIDE_FROM_ABI - friend constexpr __iterator operator-(const __iterator& __i, difference_type __n) + friend constexpr __zip_view_iterator operator-(const __zip_view_iterator& __i, difference_type __n) requires __zip_all_random_access<_Const, _Views...> { auto __r = __i; __r -= __n; @@ -389,7 +390,7 @@ } _LIBCPP_HIDE_FROM_ABI - friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) + friend constexpr difference_type operator-(const __zip_view_iterator& __x, const __zip_view_iterator& __y) requires(sized_sentinel_for>, iterator_t<__maybe_const<_Const, _Views>>> && ...) { const auto __diffs = ranges::__tuple_zip_transform(minus<>(), __x.__current_, __y.__current_); @@ -402,14 +403,14 @@ } _LIBCPP_HIDE_FROM_ABI - friend constexpr auto iter_move(const __iterator& __i) noexcept( + friend constexpr auto iter_move(const __zip_view_iterator& __i) noexcept( (noexcept(ranges::iter_move(std::declval>&>())) && ...) && (is_nothrow_move_constructible_v>> && ...)) { return ranges::__tuple_transform(ranges::iter_move, __i.__current_); } _LIBCPP_HIDE_FROM_ABI - friend constexpr void iter_swap(const __iterator& __l, const __iterator& __r) noexcept( + friend constexpr void iter_swap(const __zip_view_iterator& __l, const __zip_view_iterator& __r) noexcept( (noexcept(ranges::iter_swap(std::declval>&>(), std::declval>&>())) && ...)) @@ -418,38 +419,43 @@ } }; -template - requires(view<_Views> && ...) && (sizeof...(_Views) > 0) -template -class zip_view<_Views...>::__sentinel { +template +class __zip_view_sentinel { __tuple_or_pair>...> __end_; _LIBCPP_HIDE_FROM_ABI - constexpr explicit __sentinel(__tuple_or_pair>...> __end) : __end_(__end) {} + constexpr explicit __zip_view_sentinel(__tuple_or_pair>...> __end) + : __end_(__end) {} friend class zip_view<_Views...>; + template + friend class __zip_view_sentinel; + + template + using __iterator = __zip_view_iterator<_OtherConst, _Views...>; // hidden friend cannot access private member of iterator because they are friends of friends template _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) - __iter_current(zip_view<_Views...>::__iterator<_OtherConst> const& __it) { + __iter_current(__iterator<_OtherConst> const& __it) { return (__it.__current_); } public: _LIBCPP_HIDE_FROM_ABI - __sentinel() = default; + __zip_view_sentinel() = default; _LIBCPP_HIDE_FROM_ABI - constexpr __sentinel(__sentinel __i) + constexpr __zip_view_sentinel(__zip_view_sentinel __i) requires _Const && (convertible_to, sentinel_t<__maybe_const<_Const, _Views>>> && ...) : __end_(std::move(__i.__end_)) {} template requires(sentinel_for>, iterator_t<__maybe_const<_OtherConst, _Views>>> && ...) - _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, + const __zip_view_sentinel& __y) { return ranges::__tuple_any_equals(__iter_current(__x), __y.__end_); } @@ -458,7 +464,7 @@ sized_sentinel_for>, iterator_t<__maybe_const<_OtherConst, _Views>>> && ...) _LIBCPP_HIDE_FROM_ABI friend constexpr common_type_t>...> - operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { + operator-(const __iterator<_OtherConst>& __x, const __zip_view_sentinel& __y) { const auto __diffs = ranges::__tuple_zip_transform(minus<>(), __iter_current(__x), __y.__end_); return std::apply( [](auto... __ds) { @@ -474,7 +480,7 @@ sized_sentinel_for>, iterator_t<__maybe_const<_OtherConst, _Views>>> && ...) _LIBCPP_HIDE_FROM_ABI friend constexpr common_type_t>...> - operator-(const __sentinel& __y, const __iterator<_OtherConst>& __x) { + operator-(const __zip_view_sentinel& __y, const __iterator<_OtherConst>& __x) { return -(__x - __y); } };