181ad6265SDimitry Andric // -*- C++ -*- 281ad6265SDimitry Andric //===----------------------------------------------------------------------===// 381ad6265SDimitry Andric // 481ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 581ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 681ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 781ad6265SDimitry Andric // 881ad6265SDimitry Andric //===----------------------------------------------------------------------===// 9bdd1243dSDimitry Andric 1081ad6265SDimitry Andric #ifndef _LIBCPP___RANGES_ZIP_VIEW_H 1181ad6265SDimitry Andric #define _LIBCPP___RANGES_ZIP_VIEW_H 1281ad6265SDimitry Andric 1381ad6265SDimitry Andric #include <__config> 1481ad6265SDimitry Andric 1581ad6265SDimitry Andric #include <__algorithm/ranges_min.h> 1681ad6265SDimitry Andric #include <__compare/three_way_comparable.h> 1781ad6265SDimitry Andric #include <__concepts/convertible_to.h> 1881ad6265SDimitry Andric #include <__concepts/equality_comparable.h> 1981ad6265SDimitry Andric #include <__functional/invoke.h> 2081ad6265SDimitry Andric #include <__functional/operations.h> 2181ad6265SDimitry Andric #include <__iterator/concepts.h> 2281ad6265SDimitry Andric #include <__iterator/incrementable_traits.h> 2381ad6265SDimitry Andric #include <__iterator/iter_move.h> 2481ad6265SDimitry Andric #include <__iterator/iter_swap.h> 2581ad6265SDimitry Andric #include <__iterator/iterator_traits.h> 2681ad6265SDimitry Andric #include <__ranges/access.h> 2781ad6265SDimitry Andric #include <__ranges/all.h> 2881ad6265SDimitry Andric #include <__ranges/concepts.h> 2981ad6265SDimitry Andric #include <__ranges/empty_view.h> 3081ad6265SDimitry Andric #include <__ranges/enable_borrowed_range.h> 3181ad6265SDimitry Andric #include <__ranges/size.h> 3281ad6265SDimitry Andric #include <__ranges/view_interface.h> 33*0fca6ea1SDimitry Andric #include <__type_traits/is_nothrow_constructible.h> 3406c3fb27SDimitry Andric #include <__type_traits/make_unsigned.h> 3506c3fb27SDimitry Andric #include <__utility/declval.h> 3681ad6265SDimitry Andric #include <__utility/forward.h> 3781ad6265SDimitry Andric #include <__utility/integer_sequence.h> 3881ad6265SDimitry Andric #include <__utility/move.h> 39*0fca6ea1SDimitry Andric #include <__utility/pair.h> 4081ad6265SDimitry Andric #include <tuple> 4181ad6265SDimitry Andric 4281ad6265SDimitry Andric #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 4381ad6265SDimitry Andric # pragma GCC system_header 4481ad6265SDimitry Andric #endif 4581ad6265SDimitry Andric 4681ad6265SDimitry Andric _LIBCPP_PUSH_MACROS 4781ad6265SDimitry Andric #include <__undef_macros> 4881ad6265SDimitry Andric 4981ad6265SDimitry Andric _LIBCPP_BEGIN_NAMESPACE_STD 5081ad6265SDimitry Andric 5106c3fb27SDimitry Andric #if _LIBCPP_STD_VER >= 23 5281ad6265SDimitry Andric 5381ad6265SDimitry Andric namespace ranges { 5481ad6265SDimitry Andric 5581ad6265SDimitry Andric template <class... _Ranges> 56cb14a3feSDimitry Andric concept __zip_is_common = 57cb14a3feSDimitry Andric (sizeof...(_Ranges) == 1 && (common_range<_Ranges> && ...)) || 5881ad6265SDimitry Andric (!(bidirectional_range<_Ranges> && ...) && (common_range<_Ranges> && ...)) || 5981ad6265SDimitry Andric ((random_access_range<_Ranges> && ...) && (sized_range<_Ranges> && ...)); 6081ad6265SDimitry Andric 6181ad6265SDimitry Andric template <typename _Tp, typename _Up> 6281ad6265SDimitry Andric auto __tuple_or_pair_test() -> pair<_Tp, _Up>; 6381ad6265SDimitry Andric 6481ad6265SDimitry Andric template <typename... _Types> 6581ad6265SDimitry Andric requires(sizeof...(_Types) != 2) 6681ad6265SDimitry Andric auto __tuple_or_pair_test() -> tuple<_Types...>; 6781ad6265SDimitry Andric 6881ad6265SDimitry Andric template <class... _Types> 6981ad6265SDimitry Andric using __tuple_or_pair = decltype(__tuple_or_pair_test<_Types...>()); 7081ad6265SDimitry Andric 7181ad6265SDimitry Andric template <class _Fun, class _Tuple> 7281ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_transform(_Fun&& __f, _Tuple&& __tuple) { 7381ad6265SDimitry Andric return std::apply( 7481ad6265SDimitry Andric [&]<class... _Types>(_Types&&... __elements) { 7581ad6265SDimitry Andric return __tuple_or_pair<invoke_result_t<_Fun&, _Types>...>( 7681ad6265SDimitry Andric std::invoke(__f, std::forward<_Types>(__elements))...); 7781ad6265SDimitry Andric }, 7881ad6265SDimitry Andric std::forward<_Tuple>(__tuple)); 7981ad6265SDimitry Andric } 8081ad6265SDimitry Andric 8181ad6265SDimitry Andric template <class _Fun, class _Tuple> 8281ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void __tuple_for_each(_Fun&& __f, _Tuple&& __tuple) { 8381ad6265SDimitry Andric std::apply( 8406c3fb27SDimitry Andric [&]<class... _Types>(_Types&&... __elements) { 8506c3fb27SDimitry Andric (static_cast<void>(std::invoke(__f, std::forward<_Types>(__elements))), ...); 8606c3fb27SDimitry Andric }, 8781ad6265SDimitry Andric std::forward<_Tuple>(__tuple)); 8881ad6265SDimitry Andric } 8981ad6265SDimitry Andric 9081ad6265SDimitry Andric template <class _Fun, class _Tuple1, class _Tuple2, size_t... _Indices> 9181ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __tuple_or_pair< 92cb14a3feSDimitry Andric invoke_result_t<_Fun&, 93cb14a3feSDimitry Andric typename tuple_element<_Indices, remove_cvref_t<_Tuple1>>::type, 9481ad6265SDimitry Andric typename tuple_element<_Indices, remove_cvref_t<_Tuple2>>::type>...> 9581ad6265SDimitry Andric __tuple_zip_transform(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2, index_sequence<_Indices...>) { 96cb14a3feSDimitry Andric return {std::invoke(__f, 97cb14a3feSDimitry Andric std::get<_Indices>(std::forward<_Tuple1>(__tuple1)), 9881ad6265SDimitry Andric std::get<_Indices>(std::forward<_Tuple2>(__tuple2)))...}; 9981ad6265SDimitry Andric } 10081ad6265SDimitry Andric 10181ad6265SDimitry Andric template <class _Fun, class _Tuple1, class _Tuple2> 10281ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_transform(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2) { 103cb14a3feSDimitry Andric return ranges::__tuple_zip_transform( 104cb14a3feSDimitry Andric __f, 105cb14a3feSDimitry Andric std::forward<_Tuple1>(__tuple1), 106cb14a3feSDimitry Andric std::forward<_Tuple2>(__tuple2), 10781ad6265SDimitry Andric std::make_index_sequence<tuple_size<remove_cvref_t<_Tuple1>>::value>()); 10881ad6265SDimitry Andric } 10981ad6265SDimitry Andric 11081ad6265SDimitry Andric template <class _Fun, class _Tuple1, class _Tuple2, size_t... _Indices> 111cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void 112cb14a3feSDimitry Andric __tuple_zip_for_each(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2, index_sequence<_Indices...>) { 113cb14a3feSDimitry Andric (std::invoke( 114cb14a3feSDimitry Andric __f, std::get<_Indices>(std::forward<_Tuple1>(__tuple1)), std::get<_Indices>(std::forward<_Tuple2>(__tuple2))), 11581ad6265SDimitry Andric ...); 11681ad6265SDimitry Andric } 11781ad6265SDimitry Andric 11881ad6265SDimitry Andric template <class _Fun, class _Tuple1, class _Tuple2> 11981ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_for_each(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2) { 120cb14a3feSDimitry Andric return ranges::__tuple_zip_for_each( 121cb14a3feSDimitry Andric __f, 122cb14a3feSDimitry Andric std::forward<_Tuple1>(__tuple1), 123cb14a3feSDimitry Andric std::forward<_Tuple2>(__tuple2), 12481ad6265SDimitry Andric std::make_index_sequence<tuple_size<remove_cvref_t<_Tuple1>>::value>()); 12581ad6265SDimitry Andric } 12681ad6265SDimitry Andric 12781ad6265SDimitry Andric template <class _Tuple1, class _Tuple2> 12881ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr bool __tuple_any_equals(const _Tuple1& __tuple1, const _Tuple2& __tuple2) { 12981ad6265SDimitry Andric const auto __equals = ranges::__tuple_zip_transform(std::equal_to<>(), __tuple1, __tuple2); 13081ad6265SDimitry Andric return std::apply([](auto... __bools) { return (__bools || ...); }, __equals); 13181ad6265SDimitry Andric } 13281ad6265SDimitry Andric 13381ad6265SDimitry Andric // abs in cstdlib is not constexpr 13481ad6265SDimitry Andric // TODO : remove __abs once P0533R9 is implemented. 13581ad6265SDimitry Andric template <class _Tp> 13681ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr _Tp __abs(_Tp __t) { 13781ad6265SDimitry Andric return __t < 0 ? -__t : __t; 13881ad6265SDimitry Andric } 13981ad6265SDimitry Andric 14081ad6265SDimitry Andric template <input_range... _Views> 14181ad6265SDimitry Andric requires(view<_Views> && ...) && (sizeof...(_Views) > 0) 14281ad6265SDimitry Andric class zip_view : public view_interface<zip_view<_Views...>> { 14381ad6265SDimitry Andric _LIBCPP_NO_UNIQUE_ADDRESS tuple<_Views...> __views_; 14481ad6265SDimitry Andric 14581ad6265SDimitry Andric template <bool> 14681ad6265SDimitry Andric class __iterator; 14781ad6265SDimitry Andric 14881ad6265SDimitry Andric template <bool> 14981ad6265SDimitry Andric class __sentinel; 15081ad6265SDimitry Andric 15181ad6265SDimitry Andric public: 152cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI zip_view() = default; 15381ad6265SDimitry Andric 154cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit zip_view(_Views... __views) : __views_(std::move(__views)...) {} 15581ad6265SDimitry Andric 156cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto begin() 157cb14a3feSDimitry Andric requires(!(__simple_view<_Views> && ...)) 158cb14a3feSDimitry Andric { 15981ad6265SDimitry Andric return __iterator<false>(ranges::__tuple_transform(ranges::begin, __views_)); 16081ad6265SDimitry Andric } 16181ad6265SDimitry Andric 162cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto begin() const 163cb14a3feSDimitry Andric requires(range<const _Views> && ...) 164cb14a3feSDimitry Andric { 16581ad6265SDimitry Andric return __iterator<true>(ranges::__tuple_transform(ranges::begin, __views_)); 16681ad6265SDimitry Andric } 16781ad6265SDimitry Andric 168cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto end() 169cb14a3feSDimitry Andric requires(!(__simple_view<_Views> && ...)) 170cb14a3feSDimitry Andric { 17181ad6265SDimitry Andric if constexpr (!__zip_is_common<_Views...>) { 17281ad6265SDimitry Andric return __sentinel<false>(ranges::__tuple_transform(ranges::end, __views_)); 17381ad6265SDimitry Andric } else if constexpr ((random_access_range<_Views> && ...)) { 17481ad6265SDimitry Andric return begin() + iter_difference_t<__iterator<false>>(size()); 17581ad6265SDimitry Andric } else { 17681ad6265SDimitry Andric return __iterator<false>(ranges::__tuple_transform(ranges::end, __views_)); 17781ad6265SDimitry Andric } 17881ad6265SDimitry Andric } 17981ad6265SDimitry Andric 180cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto end() const 181cb14a3feSDimitry Andric requires(range<const _Views> && ...) 182cb14a3feSDimitry Andric { 18381ad6265SDimitry Andric if constexpr (!__zip_is_common<const _Views...>) { 18481ad6265SDimitry Andric return __sentinel<true>(ranges::__tuple_transform(ranges::end, __views_)); 18581ad6265SDimitry Andric } else if constexpr ((random_access_range<const _Views> && ...)) { 18681ad6265SDimitry Andric return begin() + iter_difference_t<__iterator<true>>(size()); 18781ad6265SDimitry Andric } else { 18881ad6265SDimitry Andric return __iterator<true>(ranges::__tuple_transform(ranges::end, __views_)); 18981ad6265SDimitry Andric } 19081ad6265SDimitry Andric } 19181ad6265SDimitry Andric 192cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto size() 193cb14a3feSDimitry Andric requires(sized_range<_Views> && ...) 194cb14a3feSDimitry Andric { 19581ad6265SDimitry Andric return std::apply( 19681ad6265SDimitry Andric [](auto... __sizes) { 19781ad6265SDimitry Andric using _CT = make_unsigned_t<common_type_t<decltype(__sizes)...>>; 19881ad6265SDimitry Andric return ranges::min({_CT(__sizes)...}); 19981ad6265SDimitry Andric }, 20081ad6265SDimitry Andric ranges::__tuple_transform(ranges::size, __views_)); 20181ad6265SDimitry Andric } 20281ad6265SDimitry Andric 203cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto size() const 204cb14a3feSDimitry Andric requires(sized_range<const _Views> && ...) 205cb14a3feSDimitry Andric { 20681ad6265SDimitry Andric return std::apply( 20781ad6265SDimitry Andric [](auto... __sizes) { 20881ad6265SDimitry Andric using _CT = make_unsigned_t<common_type_t<decltype(__sizes)...>>; 20981ad6265SDimitry Andric return ranges::min({_CT(__sizes)...}); 21081ad6265SDimitry Andric }, 21181ad6265SDimitry Andric ranges::__tuple_transform(ranges::size, __views_)); 21281ad6265SDimitry Andric } 21381ad6265SDimitry Andric }; 21481ad6265SDimitry Andric 21581ad6265SDimitry Andric template <class... _Ranges> 21681ad6265SDimitry Andric zip_view(_Ranges&&...) -> zip_view<views::all_t<_Ranges>...>; 21781ad6265SDimitry Andric 21881ad6265SDimitry Andric template <bool _Const, class... _Views> 21981ad6265SDimitry Andric concept __zip_all_random_access = (random_access_range<__maybe_const<_Const, _Views>> && ...); 22081ad6265SDimitry Andric 22181ad6265SDimitry Andric template <bool _Const, class... _Views> 22281ad6265SDimitry Andric concept __zip_all_bidirectional = (bidirectional_range<__maybe_const<_Const, _Views>> && ...); 22381ad6265SDimitry Andric 22481ad6265SDimitry Andric template <bool _Const, class... _Views> 22581ad6265SDimitry Andric concept __zip_all_forward = (forward_range<__maybe_const<_Const, _Views>> && ...); 22681ad6265SDimitry Andric 22781ad6265SDimitry Andric template <bool _Const, class... _Views> 22881ad6265SDimitry Andric consteval auto __get_zip_view_iterator_tag() { 22981ad6265SDimitry Andric if constexpr (__zip_all_random_access<_Const, _Views...>) { 23081ad6265SDimitry Andric return random_access_iterator_tag(); 23181ad6265SDimitry Andric } else if constexpr (__zip_all_bidirectional<_Const, _Views...>) { 23281ad6265SDimitry Andric return bidirectional_iterator_tag(); 23381ad6265SDimitry Andric } else if constexpr (__zip_all_forward<_Const, _Views...>) { 23481ad6265SDimitry Andric return forward_iterator_tag(); 23581ad6265SDimitry Andric } else { 23681ad6265SDimitry Andric return input_iterator_tag(); 23781ad6265SDimitry Andric } 23881ad6265SDimitry Andric } 23981ad6265SDimitry Andric 24081ad6265SDimitry Andric template <bool _Const, class... _Views> 24181ad6265SDimitry Andric struct __zip_view_iterator_category_base {}; 24281ad6265SDimitry Andric 24381ad6265SDimitry Andric template <bool _Const, class... _Views> 24481ad6265SDimitry Andric requires __zip_all_forward<_Const, _Views...> 24581ad6265SDimitry Andric struct __zip_view_iterator_category_base<_Const, _Views...> { 24681ad6265SDimitry Andric using iterator_category = input_iterator_tag; 24781ad6265SDimitry Andric }; 24881ad6265SDimitry Andric 24981ad6265SDimitry Andric template <input_range... _Views> 25081ad6265SDimitry Andric requires(view<_Views> && ...) && (sizeof...(_Views) > 0) 25181ad6265SDimitry Andric template <bool _Const> 25281ad6265SDimitry Andric class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base<_Const, _Views...> { 25381ad6265SDimitry Andric __tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current_; 25481ad6265SDimitry Andric 255cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __iterator( 256cb14a3feSDimitry Andric __tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current) 25781ad6265SDimitry Andric : __current_(std::move(__current)) {} 25881ad6265SDimitry Andric 25981ad6265SDimitry Andric template <bool> 26081ad6265SDimitry Andric friend class zip_view<_Views...>::__iterator; 26181ad6265SDimitry Andric 26281ad6265SDimitry Andric template <bool> 26381ad6265SDimitry Andric friend class zip_view<_Views...>::__sentinel; 26481ad6265SDimitry Andric 26581ad6265SDimitry Andric friend class zip_view<_Views...>; 26681ad6265SDimitry Andric 26781ad6265SDimitry Andric public: 26881ad6265SDimitry Andric using iterator_concept = decltype(__get_zip_view_iterator_tag<_Const, _Views...>()); 26981ad6265SDimitry Andric using value_type = __tuple_or_pair<range_value_t<__maybe_const<_Const, _Views>>...>; 27081ad6265SDimitry Andric using difference_type = common_type_t<range_difference_t<__maybe_const<_Const, _Views>>...>; 27181ad6265SDimitry Andric 272cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __iterator() = default; 27381ad6265SDimitry Andric 274cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator(__iterator<!_Const> __i) 27581ad6265SDimitry Andric requires _Const && (convertible_to<iterator_t<_Views>, iterator_t<__maybe_const<_Const, _Views>>> && ...) 27681ad6265SDimitry Andric : __current_(std::move(__i.__current_)) {} 27781ad6265SDimitry Andric 278cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto operator*() const { 27981ad6265SDimitry Andric return ranges::__tuple_transform([](auto& __i) -> decltype(auto) { return *__i; }, __current_); 28081ad6265SDimitry Andric } 28181ad6265SDimitry Andric 282cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator++() { 28381ad6265SDimitry Andric ranges::__tuple_for_each([](auto& __i) { ++__i; }, __current_); 28481ad6265SDimitry Andric return *this; 28581ad6265SDimitry Andric } 28681ad6265SDimitry Andric 287cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr void operator++(int) { ++*this; } 28881ad6265SDimitry Andric 289cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator++(int) 290cb14a3feSDimitry Andric requires __zip_all_forward<_Const, _Views...> 291cb14a3feSDimitry Andric { 29281ad6265SDimitry Andric auto __tmp = *this; 29381ad6265SDimitry Andric ++*this; 29481ad6265SDimitry Andric return __tmp; 29581ad6265SDimitry Andric } 29681ad6265SDimitry Andric 297cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator--() 298cb14a3feSDimitry Andric requires __zip_all_bidirectional<_Const, _Views...> 299cb14a3feSDimitry Andric { 30081ad6265SDimitry Andric ranges::__tuple_for_each([](auto& __i) { --__i; }, __current_); 30181ad6265SDimitry Andric return *this; 30281ad6265SDimitry Andric } 30381ad6265SDimitry Andric 304cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator operator--(int) 305cb14a3feSDimitry Andric requires __zip_all_bidirectional<_Const, _Views...> 306cb14a3feSDimitry Andric { 30781ad6265SDimitry Andric auto __tmp = *this; 30881ad6265SDimitry Andric --*this; 30981ad6265SDimitry Andric return __tmp; 31081ad6265SDimitry Andric } 31181ad6265SDimitry Andric 312cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator+=(difference_type __x) 313cb14a3feSDimitry Andric requires __zip_all_random_access<_Const, _Views...> 314cb14a3feSDimitry Andric { 31581ad6265SDimitry Andric ranges::__tuple_for_each([&]<class _Iter>(_Iter& __i) { __i += iter_difference_t<_Iter>(__x); }, __current_); 31681ad6265SDimitry Andric return *this; 31781ad6265SDimitry Andric } 31881ad6265SDimitry Andric 319cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __iterator& operator-=(difference_type __x) 320cb14a3feSDimitry Andric requires __zip_all_random_access<_Const, _Views...> 321cb14a3feSDimitry Andric { 32281ad6265SDimitry Andric ranges::__tuple_for_each([&]<class _Iter>(_Iter& __i) { __i -= iter_difference_t<_Iter>(__x); }, __current_); 32381ad6265SDimitry Andric return *this; 32481ad6265SDimitry Andric } 32581ad6265SDimitry Andric 326cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr auto operator[](difference_type __n) const 327cb14a3feSDimitry Andric requires __zip_all_random_access<_Const, _Views...> 328cb14a3feSDimitry Andric { 32981ad6265SDimitry Andric return ranges::__tuple_transform( 33081ad6265SDimitry Andric [&]<class _Iter>(_Iter& __i) -> decltype(auto) { return __i[iter_difference_t<_Iter>(__n)]; }, __current_); 33181ad6265SDimitry Andric } 33281ad6265SDimitry Andric 333cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator& __x, const __iterator& __y) 334cb14a3feSDimitry Andric requires(equality_comparable<iterator_t<__maybe_const<_Const, _Views>>> && ...) 335cb14a3feSDimitry Andric { 33681ad6265SDimitry Andric if constexpr (__zip_all_bidirectional<_Const, _Views...>) { 33781ad6265SDimitry Andric return __x.__current_ == __y.__current_; 33881ad6265SDimitry Andric } else { 33981ad6265SDimitry Andric return ranges::__tuple_any_equals(__x.__current_, __y.__current_); 34081ad6265SDimitry Andric } 34181ad6265SDimitry Andric } 34281ad6265SDimitry Andric 343cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<(const __iterator& __x, const __iterator& __y) 344cb14a3feSDimitry Andric requires __zip_all_random_access<_Const, _Views...> 345cb14a3feSDimitry Andric { 34681ad6265SDimitry Andric return __x.__current_ < __y.__current_; 34781ad6265SDimitry Andric } 34881ad6265SDimitry Andric 349cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>(const __iterator& __x, const __iterator& __y) 350cb14a3feSDimitry Andric requires __zip_all_random_access<_Const, _Views...> 351cb14a3feSDimitry Andric { 35281ad6265SDimitry Andric return __y < __x; 35381ad6265SDimitry Andric } 35481ad6265SDimitry Andric 355cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y) 356cb14a3feSDimitry Andric requires __zip_all_random_access<_Const, _Views...> 357cb14a3feSDimitry Andric { 35881ad6265SDimitry Andric return !(__y < __x); 35981ad6265SDimitry Andric } 36081ad6265SDimitry Andric 361cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y) 362cb14a3feSDimitry Andric requires __zip_all_random_access<_Const, _Views...> 363cb14a3feSDimitry Andric { 36481ad6265SDimitry Andric return !(__x < __y); 36581ad6265SDimitry Andric } 36681ad6265SDimitry Andric 367cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y) 36881ad6265SDimitry Andric requires __zip_all_random_access<_Const, _Views...> && 369cb14a3feSDimitry Andric (three_way_comparable<iterator_t<__maybe_const<_Const, _Views>>> && ...) 370cb14a3feSDimitry Andric { 37181ad6265SDimitry Andric return __x.__current_ <=> __y.__current_; 37281ad6265SDimitry Andric } 37381ad6265SDimitry Andric 374cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(const __iterator& __i, difference_type __n) 375cb14a3feSDimitry Andric requires __zip_all_random_access<_Const, _Views...> 376cb14a3feSDimitry Andric { 37781ad6265SDimitry Andric auto __r = __i; 37881ad6265SDimitry Andric __r += __n; 37981ad6265SDimitry Andric return __r; 38081ad6265SDimitry Andric } 38181ad6265SDimitry Andric 382cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator+(difference_type __n, const __iterator& __i) 383cb14a3feSDimitry Andric requires __zip_all_random_access<_Const, _Views...> 384cb14a3feSDimitry Andric { 38581ad6265SDimitry Andric return __i + __n; 38681ad6265SDimitry Andric } 38781ad6265SDimitry Andric 388cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr __iterator operator-(const __iterator& __i, difference_type __n) 389cb14a3feSDimitry Andric requires __zip_all_random_access<_Const, _Views...> 390cb14a3feSDimitry Andric { 39181ad6265SDimitry Andric auto __r = __i; 39281ad6265SDimitry Andric __r -= __n; 39381ad6265SDimitry Andric return __r; 39481ad6265SDimitry Andric } 39581ad6265SDimitry Andric 396cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y) 39781ad6265SDimitry Andric requires(sized_sentinel_for<iterator_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_Const, _Views>>> && 398cb14a3feSDimitry Andric ...) 399cb14a3feSDimitry Andric { 40081ad6265SDimitry Andric const auto __diffs = ranges::__tuple_zip_transform(minus<>(), __x.__current_, __y.__current_); 40181ad6265SDimitry Andric return std::apply( 40281ad6265SDimitry Andric [](auto... __ds) { 403cb14a3feSDimitry Andric return ranges::min({difference_type(__ds)...}, [](auto __a, auto __b) { 404cb14a3feSDimitry Andric return ranges::__abs(__a) < ranges::__abs(__b); 405cb14a3feSDimitry Andric }); 40681ad6265SDimitry Andric }, 40781ad6265SDimitry Andric __diffs); 40881ad6265SDimitry Andric } 40981ad6265SDimitry Andric 410cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr auto iter_move(const __iterator& __i) noexcept( 411bdd1243dSDimitry Andric (noexcept(ranges::iter_move(std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && ...) && 41281ad6265SDimitry Andric (is_nothrow_move_constructible_v<range_rvalue_reference_t<__maybe_const<_Const, _Views>>> && ...)) { 41381ad6265SDimitry Andric return ranges::__tuple_transform(ranges::iter_move, __i.__current_); 41481ad6265SDimitry Andric } 41581ad6265SDimitry Andric 416cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr void iter_swap(const __iterator& __l, const __iterator& __r) noexcept( 417bdd1243dSDimitry Andric (noexcept(ranges::iter_swap(std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>(), 418bdd1243dSDimitry Andric std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && 41981ad6265SDimitry Andric ...)) 420cb14a3feSDimitry Andric requires(indirectly_swappable<iterator_t<__maybe_const<_Const, _Views>>> && ...) 421cb14a3feSDimitry Andric { 42281ad6265SDimitry Andric ranges::__tuple_zip_for_each(ranges::iter_swap, __l.__current_, __r.__current_); 42381ad6265SDimitry Andric } 42481ad6265SDimitry Andric }; 42581ad6265SDimitry Andric 42681ad6265SDimitry Andric template <input_range... _Views> 42781ad6265SDimitry Andric requires(view<_Views> && ...) && (sizeof...(_Views) > 0) 42881ad6265SDimitry Andric template <bool _Const> 42981ad6265SDimitry Andric class zip_view<_Views...>::__sentinel { 43081ad6265SDimitry Andric __tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end_; 43181ad6265SDimitry Andric 432cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr explicit __sentinel( 433cb14a3feSDimitry Andric __tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end) 434cb14a3feSDimitry Andric : __end_(__end) {} 43581ad6265SDimitry Andric 43681ad6265SDimitry Andric friend class zip_view<_Views...>; 43781ad6265SDimitry Andric 43881ad6265SDimitry Andric // hidden friend cannot access private member of iterator because they are friends of friends 43981ad6265SDimitry Andric template <bool _OtherConst> 44081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto) 44181ad6265SDimitry Andric __iter_current(zip_view<_Views...>::__iterator<_OtherConst> const& __it) { 44281ad6265SDimitry Andric return (__it.__current_); 44381ad6265SDimitry Andric } 44481ad6265SDimitry Andric 44581ad6265SDimitry Andric public: 446cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI __sentinel() = default; 44781ad6265SDimitry Andric 448cb14a3feSDimitry Andric _LIBCPP_HIDE_FROM_ABI constexpr __sentinel(__sentinel<!_Const> __i) 44981ad6265SDimitry Andric requires _Const && (convertible_to<sentinel_t<_Views>, sentinel_t<__maybe_const<_Const, _Views>>> && ...) 45081ad6265SDimitry Andric : __end_(std::move(__i.__end_)) {} 45181ad6265SDimitry Andric 45281ad6265SDimitry Andric template <bool _OtherConst> 45381ad6265SDimitry Andric requires(sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_OtherConst, _Views>>> && 45481ad6265SDimitry Andric ...) 45581ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) { 45681ad6265SDimitry Andric return ranges::__tuple_any_equals(__iter_current(__x), __y.__end_); 45781ad6265SDimitry Andric } 45881ad6265SDimitry Andric 45981ad6265SDimitry Andric template <bool _OtherConst> 46081ad6265SDimitry Andric requires( 46181ad6265SDimitry Andric sized_sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_OtherConst, _Views>>> && 46281ad6265SDimitry Andric ...) 46381ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr common_type_t<range_difference_t<__maybe_const<_OtherConst, _Views>>...> 46481ad6265SDimitry Andric operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) { 46581ad6265SDimitry Andric const auto __diffs = ranges::__tuple_zip_transform(minus<>(), __iter_current(__x), __y.__end_); 46681ad6265SDimitry Andric return std::apply( 46781ad6265SDimitry Andric [](auto... __ds) { 46881ad6265SDimitry Andric using _Diff = common_type_t<range_difference_t<__maybe_const<_OtherConst, _Views>>...>; 469cb14a3feSDimitry Andric return ranges::min({_Diff(__ds)...}, [](auto __a, auto __b) { 470cb14a3feSDimitry Andric return ranges::__abs(__a) < ranges::__abs(__b); 471cb14a3feSDimitry Andric }); 47281ad6265SDimitry Andric }, 47381ad6265SDimitry Andric __diffs); 47481ad6265SDimitry Andric } 47581ad6265SDimitry Andric 47681ad6265SDimitry Andric template <bool _OtherConst> 47781ad6265SDimitry Andric requires( 47881ad6265SDimitry Andric sized_sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_OtherConst, _Views>>> && 47981ad6265SDimitry Andric ...) 48081ad6265SDimitry Andric _LIBCPP_HIDE_FROM_ABI friend constexpr common_type_t<range_difference_t<__maybe_const<_OtherConst, _Views>>...> 48181ad6265SDimitry Andric operator-(const __sentinel& __y, const __iterator<_OtherConst>& __x) { 48281ad6265SDimitry Andric return -(__x - __y); 48381ad6265SDimitry Andric } 48481ad6265SDimitry Andric }; 48581ad6265SDimitry Andric 48681ad6265SDimitry Andric template <class... _Views> 48781ad6265SDimitry Andric inline constexpr bool enable_borrowed_range<zip_view<_Views...>> = (enable_borrowed_range<_Views> && ...); 48881ad6265SDimitry Andric 48981ad6265SDimitry Andric namespace views { 49081ad6265SDimitry Andric namespace __zip { 49181ad6265SDimitry Andric 49281ad6265SDimitry Andric struct __fn { 493*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr auto operator()() noexcept { return empty_view<tuple<>>{}; } 49481ad6265SDimitry Andric 49581ad6265SDimitry Andric template <class... _Ranges> 496*0fca6ea1SDimitry Andric _LIBCPP_HIDE_FROM_ABI static constexpr auto 497*0fca6ea1SDimitry Andric operator()(_Ranges&&... __rs) noexcept(noexcept(zip_view<all_t<_Ranges&&>...>(std::forward<_Ranges>(__rs)...))) 498753f127fSDimitry Andric -> decltype(zip_view<all_t<_Ranges&&>...>(std::forward<_Ranges>(__rs)...)) { 499753f127fSDimitry Andric return zip_view<all_t<_Ranges>...>(std::forward<_Ranges>(__rs)...); 50081ad6265SDimitry Andric } 50181ad6265SDimitry Andric }; 50281ad6265SDimitry Andric 50381ad6265SDimitry Andric } // namespace __zip 50481ad6265SDimitry Andric inline namespace __cpo { 50581ad6265SDimitry Andric inline constexpr auto zip = __zip::__fn{}; 50681ad6265SDimitry Andric } // namespace __cpo 50781ad6265SDimitry Andric } // namespace views 50881ad6265SDimitry Andric } // namespace ranges 50981ad6265SDimitry Andric 51006c3fb27SDimitry Andric #endif // _LIBCPP_STD_VER >= 23 51181ad6265SDimitry Andric 51281ad6265SDimitry Andric _LIBCPP_END_NAMESPACE_STD 51381ad6265SDimitry Andric 51481ad6265SDimitry Andric _LIBCPP_POP_MACROS 51581ad6265SDimitry Andric 51681ad6265SDimitry Andric #endif // _LIBCPP___RANGES_ZIP_VIEW_H 517