1*4bdff4beSrobert // -*- C++ -*-
2*4bdff4beSrobert //===----------------------------------------------------------------------===//
3*4bdff4beSrobert //
4*4bdff4beSrobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*4bdff4beSrobert // See https://llvm.org/LICENSE.txt for license information.
6*4bdff4beSrobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*4bdff4beSrobert //
8*4bdff4beSrobert //===----------------------------------------------------------------------===//
9*4bdff4beSrobert
10*4bdff4beSrobert #ifndef _LIBCPP___RANGES_ZIP_VIEW_H
11*4bdff4beSrobert #define _LIBCPP___RANGES_ZIP_VIEW_H
12*4bdff4beSrobert
13*4bdff4beSrobert #include <__config>
14*4bdff4beSrobert
15*4bdff4beSrobert #include <__algorithm/ranges_min.h>
16*4bdff4beSrobert #include <__compare/three_way_comparable.h>
17*4bdff4beSrobert #include <__concepts/convertible_to.h>
18*4bdff4beSrobert #include <__concepts/equality_comparable.h>
19*4bdff4beSrobert #include <__functional/invoke.h>
20*4bdff4beSrobert #include <__functional/operations.h>
21*4bdff4beSrobert #include <__iterator/concepts.h>
22*4bdff4beSrobert #include <__iterator/incrementable_traits.h>
23*4bdff4beSrobert #include <__iterator/iter_move.h>
24*4bdff4beSrobert #include <__iterator/iter_swap.h>
25*4bdff4beSrobert #include <__iterator/iterator_traits.h>
26*4bdff4beSrobert #include <__ranges/access.h>
27*4bdff4beSrobert #include <__ranges/all.h>
28*4bdff4beSrobert #include <__ranges/concepts.h>
29*4bdff4beSrobert #include <__ranges/empty_view.h>
30*4bdff4beSrobert #include <__ranges/enable_borrowed_range.h>
31*4bdff4beSrobert #include <__ranges/size.h>
32*4bdff4beSrobert #include <__ranges/view_interface.h>
33*4bdff4beSrobert #include <__utility/forward.h>
34*4bdff4beSrobert #include <__utility/integer_sequence.h>
35*4bdff4beSrobert #include <__utility/move.h>
36*4bdff4beSrobert #include <tuple>
37*4bdff4beSrobert #include <type_traits>
38*4bdff4beSrobert
39*4bdff4beSrobert #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
40*4bdff4beSrobert # pragma GCC system_header
41*4bdff4beSrobert #endif
42*4bdff4beSrobert
43*4bdff4beSrobert _LIBCPP_PUSH_MACROS
44*4bdff4beSrobert #include <__undef_macros>
45*4bdff4beSrobert
46*4bdff4beSrobert _LIBCPP_BEGIN_NAMESPACE_STD
47*4bdff4beSrobert
48*4bdff4beSrobert #if _LIBCPP_STD_VER > 20
49*4bdff4beSrobert
50*4bdff4beSrobert namespace ranges {
51*4bdff4beSrobert
52*4bdff4beSrobert template <class... _Ranges>
53*4bdff4beSrobert concept __zip_is_common = (sizeof...(_Ranges) == 1 && (common_range<_Ranges> && ...)) ||
54*4bdff4beSrobert (!(bidirectional_range<_Ranges> && ...) && (common_range<_Ranges> && ...)) ||
55*4bdff4beSrobert ((random_access_range<_Ranges> && ...) && (sized_range<_Ranges> && ...));
56*4bdff4beSrobert
57*4bdff4beSrobert template <typename _Tp, typename _Up>
58*4bdff4beSrobert auto __tuple_or_pair_test() -> pair<_Tp, _Up>;
59*4bdff4beSrobert
60*4bdff4beSrobert template <typename... _Types>
61*4bdff4beSrobert requires(sizeof...(_Types) != 2)
62*4bdff4beSrobert auto __tuple_or_pair_test() -> tuple<_Types...>;
63*4bdff4beSrobert
64*4bdff4beSrobert template <class... _Types>
65*4bdff4beSrobert using __tuple_or_pair = decltype(__tuple_or_pair_test<_Types...>());
66*4bdff4beSrobert
67*4bdff4beSrobert template <class _Fun, class _Tuple>
__tuple_transform(_Fun && __f,_Tuple && __tuple)68*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_transform(_Fun&& __f, _Tuple&& __tuple) {
69*4bdff4beSrobert return std::apply(
70*4bdff4beSrobert [&]<class... _Types>(_Types&&... __elements) {
71*4bdff4beSrobert return __tuple_or_pair<invoke_result_t<_Fun&, _Types>...>(
72*4bdff4beSrobert std::invoke(__f, std::forward<_Types>(__elements))...);
73*4bdff4beSrobert },
74*4bdff4beSrobert std::forward<_Tuple>(__tuple));
75*4bdff4beSrobert }
76*4bdff4beSrobert
77*4bdff4beSrobert template <class _Fun, class _Tuple>
__tuple_for_each(_Fun && __f,_Tuple && __tuple)78*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr void __tuple_for_each(_Fun&& __f, _Tuple&& __tuple) {
79*4bdff4beSrobert std::apply(
80*4bdff4beSrobert [&]<class... _Types>(_Types&&... __elements) { (std::invoke(__f, std::forward<_Types>(__elements)), ...); },
81*4bdff4beSrobert std::forward<_Tuple>(__tuple));
82*4bdff4beSrobert }
83*4bdff4beSrobert
84*4bdff4beSrobert template <class _Fun, class _Tuple1, class _Tuple2, size_t... _Indices>
85*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr __tuple_or_pair<
86*4bdff4beSrobert invoke_result_t<_Fun&, typename tuple_element<_Indices, remove_cvref_t<_Tuple1>>::type,
87*4bdff4beSrobert typename tuple_element<_Indices, remove_cvref_t<_Tuple2>>::type>...>
__tuple_zip_transform(_Fun && __f,_Tuple1 && __tuple1,_Tuple2 && __tuple2,index_sequence<_Indices...>)88*4bdff4beSrobert __tuple_zip_transform(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2, index_sequence<_Indices...>) {
89*4bdff4beSrobert return {std::invoke(__f, std::get<_Indices>(std::forward<_Tuple1>(__tuple1)),
90*4bdff4beSrobert std::get<_Indices>(std::forward<_Tuple2>(__tuple2)))...};
91*4bdff4beSrobert }
92*4bdff4beSrobert
93*4bdff4beSrobert template <class _Fun, class _Tuple1, class _Tuple2>
__tuple_zip_transform(_Fun && __f,_Tuple1 && __tuple1,_Tuple2 && __tuple2)94*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_transform(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2) {
95*4bdff4beSrobert return ranges::__tuple_zip_transform(__f, std::forward<_Tuple1>(__tuple1), std::forward<_Tuple2>(__tuple2),
96*4bdff4beSrobert std::make_index_sequence<tuple_size<remove_cvref_t<_Tuple1>>::value>());
97*4bdff4beSrobert }
98*4bdff4beSrobert
99*4bdff4beSrobert template <class _Fun, class _Tuple1, class _Tuple2, size_t... _Indices>
__tuple_zip_for_each(_Fun && __f,_Tuple1 && __tuple1,_Tuple2 && __tuple2,index_sequence<_Indices...>)100*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr void __tuple_zip_for_each(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2,
101*4bdff4beSrobert index_sequence<_Indices...>) {
102*4bdff4beSrobert (std::invoke(__f, std::get<_Indices>(std::forward<_Tuple1>(__tuple1)),
103*4bdff4beSrobert std::get<_Indices>(std::forward<_Tuple2>(__tuple2))),
104*4bdff4beSrobert ...);
105*4bdff4beSrobert }
106*4bdff4beSrobert
107*4bdff4beSrobert template <class _Fun, class _Tuple1, class _Tuple2>
__tuple_zip_for_each(_Fun && __f,_Tuple1 && __tuple1,_Tuple2 && __tuple2)108*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr auto __tuple_zip_for_each(_Fun&& __f, _Tuple1&& __tuple1, _Tuple2&& __tuple2) {
109*4bdff4beSrobert return ranges::__tuple_zip_for_each(__f, std::forward<_Tuple1>(__tuple1), std::forward<_Tuple2>(__tuple2),
110*4bdff4beSrobert std::make_index_sequence<tuple_size<remove_cvref_t<_Tuple1>>::value>());
111*4bdff4beSrobert }
112*4bdff4beSrobert
113*4bdff4beSrobert template <class _Tuple1, class _Tuple2>
__tuple_any_equals(const _Tuple1 & __tuple1,const _Tuple2 & __tuple2)114*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr bool __tuple_any_equals(const _Tuple1& __tuple1, const _Tuple2& __tuple2) {
115*4bdff4beSrobert const auto __equals = ranges::__tuple_zip_transform(std::equal_to<>(), __tuple1, __tuple2);
116*4bdff4beSrobert return std::apply([](auto... __bools) { return (__bools || ...); }, __equals);
117*4bdff4beSrobert }
118*4bdff4beSrobert
119*4bdff4beSrobert // abs in cstdlib is not constexpr
120*4bdff4beSrobert // TODO : remove __abs once P0533R9 is implemented.
121*4bdff4beSrobert template <class _Tp>
__abs(_Tp __t)122*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr _Tp __abs(_Tp __t) {
123*4bdff4beSrobert return __t < 0 ? -__t : __t;
124*4bdff4beSrobert }
125*4bdff4beSrobert
126*4bdff4beSrobert template <input_range... _Views>
requires(view<_Views> &&...)127*4bdff4beSrobert requires(view<_Views> && ...) && (sizeof...(_Views) > 0)
128*4bdff4beSrobert class zip_view : public view_interface<zip_view<_Views...>> {
129*4bdff4beSrobert
130*4bdff4beSrobert _LIBCPP_NO_UNIQUE_ADDRESS tuple<_Views...> __views_;
131*4bdff4beSrobert
132*4bdff4beSrobert template <bool>
133*4bdff4beSrobert class __iterator;
134*4bdff4beSrobert
135*4bdff4beSrobert template <bool>
136*4bdff4beSrobert class __sentinel;
137*4bdff4beSrobert
138*4bdff4beSrobert public:
139*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
140*4bdff4beSrobert zip_view() = default;
141*4bdff4beSrobert
142*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
143*4bdff4beSrobert constexpr explicit zip_view(_Views... __views) : __views_(std::move(__views)...) {}
144*4bdff4beSrobert
145*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
146*4bdff4beSrobert constexpr auto begin()
147*4bdff4beSrobert requires(!(__simple_view<_Views> && ...)) {
148*4bdff4beSrobert return __iterator<false>(ranges::__tuple_transform(ranges::begin, __views_));
149*4bdff4beSrobert }
150*4bdff4beSrobert
151*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
152*4bdff4beSrobert constexpr auto begin() const
153*4bdff4beSrobert requires(range<const _Views> && ...) {
154*4bdff4beSrobert return __iterator<true>(ranges::__tuple_transform(ranges::begin, __views_));
155*4bdff4beSrobert }
156*4bdff4beSrobert
157*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
158*4bdff4beSrobert constexpr auto end()
159*4bdff4beSrobert requires(!(__simple_view<_Views> && ...)) {
160*4bdff4beSrobert if constexpr (!__zip_is_common<_Views...>) {
161*4bdff4beSrobert return __sentinel<false>(ranges::__tuple_transform(ranges::end, __views_));
162*4bdff4beSrobert } else if constexpr ((random_access_range<_Views> && ...)) {
163*4bdff4beSrobert return begin() + iter_difference_t<__iterator<false>>(size());
164*4bdff4beSrobert } else {
165*4bdff4beSrobert return __iterator<false>(ranges::__tuple_transform(ranges::end, __views_));
166*4bdff4beSrobert }
167*4bdff4beSrobert }
168*4bdff4beSrobert
169*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
170*4bdff4beSrobert constexpr auto end() const
171*4bdff4beSrobert requires(range<const _Views> && ...) {
172*4bdff4beSrobert if constexpr (!__zip_is_common<const _Views...>) {
173*4bdff4beSrobert return __sentinel<true>(ranges::__tuple_transform(ranges::end, __views_));
174*4bdff4beSrobert } else if constexpr ((random_access_range<const _Views> && ...)) {
175*4bdff4beSrobert return begin() + iter_difference_t<__iterator<true>>(size());
176*4bdff4beSrobert } else {
177*4bdff4beSrobert return __iterator<true>(ranges::__tuple_transform(ranges::end, __views_));
178*4bdff4beSrobert }
179*4bdff4beSrobert }
180*4bdff4beSrobert
181*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
182*4bdff4beSrobert constexpr auto size()
183*4bdff4beSrobert requires(sized_range<_Views> && ...) {
184*4bdff4beSrobert return std::apply(
185*4bdff4beSrobert [](auto... __sizes) {
186*4bdff4beSrobert using _CT = make_unsigned_t<common_type_t<decltype(__sizes)...>>;
187*4bdff4beSrobert return ranges::min({_CT(__sizes)...});
188*4bdff4beSrobert },
189*4bdff4beSrobert ranges::__tuple_transform(ranges::size, __views_));
190*4bdff4beSrobert }
191*4bdff4beSrobert
192*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
193*4bdff4beSrobert constexpr auto size() const
194*4bdff4beSrobert requires(sized_range<const _Views> && ...) {
195*4bdff4beSrobert return std::apply(
196*4bdff4beSrobert [](auto... __sizes) {
197*4bdff4beSrobert using _CT = make_unsigned_t<common_type_t<decltype(__sizes)...>>;
198*4bdff4beSrobert return ranges::min({_CT(__sizes)...});
199*4bdff4beSrobert },
200*4bdff4beSrobert ranges::__tuple_transform(ranges::size, __views_));
201*4bdff4beSrobert }
202*4bdff4beSrobert };
203*4bdff4beSrobert
204*4bdff4beSrobert template <class... _Ranges>
205*4bdff4beSrobert zip_view(_Ranges&&...) -> zip_view<views::all_t<_Ranges>...>;
206*4bdff4beSrobert
207*4bdff4beSrobert template <bool _Const, class... _Views>
208*4bdff4beSrobert concept __zip_all_random_access = (random_access_range<__maybe_const<_Const, _Views>> && ...);
209*4bdff4beSrobert
210*4bdff4beSrobert template <bool _Const, class... _Views>
211*4bdff4beSrobert concept __zip_all_bidirectional = (bidirectional_range<__maybe_const<_Const, _Views>> && ...);
212*4bdff4beSrobert
213*4bdff4beSrobert template <bool _Const, class... _Views>
214*4bdff4beSrobert concept __zip_all_forward = (forward_range<__maybe_const<_Const, _Views>> && ...);
215*4bdff4beSrobert
216*4bdff4beSrobert template <bool _Const, class... _Views>
__get_zip_view_iterator_tag()217*4bdff4beSrobert consteval auto __get_zip_view_iterator_tag() {
218*4bdff4beSrobert if constexpr (__zip_all_random_access<_Const, _Views...>) {
219*4bdff4beSrobert return random_access_iterator_tag();
220*4bdff4beSrobert } else if constexpr (__zip_all_bidirectional<_Const, _Views...>) {
221*4bdff4beSrobert return bidirectional_iterator_tag();
222*4bdff4beSrobert } else if constexpr (__zip_all_forward<_Const, _Views...>) {
223*4bdff4beSrobert return forward_iterator_tag();
224*4bdff4beSrobert } else {
225*4bdff4beSrobert return input_iterator_tag();
226*4bdff4beSrobert }
227*4bdff4beSrobert }
228*4bdff4beSrobert
229*4bdff4beSrobert template <bool _Const, class... _Views>
230*4bdff4beSrobert struct __zip_view_iterator_category_base {};
231*4bdff4beSrobert
232*4bdff4beSrobert template <bool _Const, class... _Views>
233*4bdff4beSrobert requires __zip_all_forward<_Const, _Views...>
234*4bdff4beSrobert struct __zip_view_iterator_category_base<_Const, _Views...> {
235*4bdff4beSrobert using iterator_category = input_iterator_tag;
236*4bdff4beSrobert };
237*4bdff4beSrobert
238*4bdff4beSrobert template <input_range... _Views>
239*4bdff4beSrobert requires(view<_Views> && ...) && (sizeof...(_Views) > 0)
240*4bdff4beSrobert template <bool _Const>
241*4bdff4beSrobert class zip_view<_Views...>::__iterator : public __zip_view_iterator_category_base<_Const, _Views...> {
242*4bdff4beSrobert
243*4bdff4beSrobert __tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current_;
244*4bdff4beSrobert
245*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
246*4bdff4beSrobert constexpr explicit __iterator(__tuple_or_pair<iterator_t<__maybe_const<_Const, _Views>>...> __current)
247*4bdff4beSrobert : __current_(std::move(__current)) {}
248*4bdff4beSrobert
249*4bdff4beSrobert template <bool>
250*4bdff4beSrobert friend class zip_view<_Views...>::__iterator;
251*4bdff4beSrobert
252*4bdff4beSrobert template <bool>
253*4bdff4beSrobert friend class zip_view<_Views...>::__sentinel;
254*4bdff4beSrobert
255*4bdff4beSrobert friend class zip_view<_Views...>;
256*4bdff4beSrobert
257*4bdff4beSrobert public:
258*4bdff4beSrobert using iterator_concept = decltype(__get_zip_view_iterator_tag<_Const, _Views...>());
259*4bdff4beSrobert using value_type = __tuple_or_pair<range_value_t<__maybe_const<_Const, _Views>>...>;
260*4bdff4beSrobert using difference_type = common_type_t<range_difference_t<__maybe_const<_Const, _Views>>...>;
261*4bdff4beSrobert
262*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
263*4bdff4beSrobert __iterator() = default;
264*4bdff4beSrobert
265*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
266*4bdff4beSrobert constexpr __iterator(__iterator<!_Const> __i)
267*4bdff4beSrobert requires _Const && (convertible_to<iterator_t<_Views>, iterator_t<__maybe_const<_Const, _Views>>> && ...)
268*4bdff4beSrobert : __current_(std::move(__i.__current_)) {}
269*4bdff4beSrobert
270*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
271*4bdff4beSrobert constexpr auto operator*() const {
272*4bdff4beSrobert return ranges::__tuple_transform([](auto& __i) -> decltype(auto) { return *__i; }, __current_);
273*4bdff4beSrobert }
274*4bdff4beSrobert
275*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
276*4bdff4beSrobert constexpr __iterator& operator++() {
277*4bdff4beSrobert ranges::__tuple_for_each([](auto& __i) { ++__i; }, __current_);
278*4bdff4beSrobert return *this;
279*4bdff4beSrobert }
280*4bdff4beSrobert
281*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
282*4bdff4beSrobert constexpr void operator++(int) { ++*this; }
283*4bdff4beSrobert
284*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
285*4bdff4beSrobert constexpr __iterator operator++(int)
286*4bdff4beSrobert requires __zip_all_forward<_Const, _Views...> {
287*4bdff4beSrobert auto __tmp = *this;
288*4bdff4beSrobert ++*this;
289*4bdff4beSrobert return __tmp;
290*4bdff4beSrobert }
291*4bdff4beSrobert
292*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
293*4bdff4beSrobert constexpr __iterator& operator--()
294*4bdff4beSrobert requires __zip_all_bidirectional<_Const, _Views...> {
295*4bdff4beSrobert ranges::__tuple_for_each([](auto& __i) { --__i; }, __current_);
296*4bdff4beSrobert return *this;
297*4bdff4beSrobert }
298*4bdff4beSrobert
299*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
300*4bdff4beSrobert constexpr __iterator operator--(int)
301*4bdff4beSrobert requires __zip_all_bidirectional<_Const, _Views...> {
302*4bdff4beSrobert auto __tmp = *this;
303*4bdff4beSrobert --*this;
304*4bdff4beSrobert return __tmp;
305*4bdff4beSrobert }
306*4bdff4beSrobert
307*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
308*4bdff4beSrobert constexpr __iterator& operator+=(difference_type __x)
309*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> {
310*4bdff4beSrobert ranges::__tuple_for_each([&]<class _Iter>(_Iter& __i) { __i += iter_difference_t<_Iter>(__x); }, __current_);
311*4bdff4beSrobert return *this;
312*4bdff4beSrobert }
313*4bdff4beSrobert
314*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
315*4bdff4beSrobert constexpr __iterator& operator-=(difference_type __x)
316*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> {
317*4bdff4beSrobert ranges::__tuple_for_each([&]<class _Iter>(_Iter& __i) { __i -= iter_difference_t<_Iter>(__x); }, __current_);
318*4bdff4beSrobert return *this;
319*4bdff4beSrobert }
320*4bdff4beSrobert
321*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
322*4bdff4beSrobert constexpr auto operator[](difference_type __n) const
323*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> {
324*4bdff4beSrobert return ranges::__tuple_transform(
325*4bdff4beSrobert [&]<class _Iter>(_Iter& __i) -> decltype(auto) { return __i[iter_difference_t<_Iter>(__n)]; }, __current_);
326*4bdff4beSrobert }
327*4bdff4beSrobert
328*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
329*4bdff4beSrobert friend constexpr bool operator==(const __iterator& __x, const __iterator& __y)
330*4bdff4beSrobert requires(equality_comparable<iterator_t<__maybe_const<_Const, _Views>>> && ...) {
331*4bdff4beSrobert if constexpr (__zip_all_bidirectional<_Const, _Views...>) {
332*4bdff4beSrobert return __x.__current_ == __y.__current_;
333*4bdff4beSrobert } else {
334*4bdff4beSrobert return ranges::__tuple_any_equals(__x.__current_, __y.__current_);
335*4bdff4beSrobert }
336*4bdff4beSrobert }
337*4bdff4beSrobert
338*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
339*4bdff4beSrobert friend constexpr bool operator<(const __iterator& __x, const __iterator& __y)
340*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> {
341*4bdff4beSrobert return __x.__current_ < __y.__current_;
342*4bdff4beSrobert }
343*4bdff4beSrobert
344*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
345*4bdff4beSrobert friend constexpr bool operator>(const __iterator& __x, const __iterator& __y)
346*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> {
347*4bdff4beSrobert return __y < __x;
348*4bdff4beSrobert }
349*4bdff4beSrobert
350*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
351*4bdff4beSrobert friend constexpr bool operator<=(const __iterator& __x, const __iterator& __y)
352*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> {
353*4bdff4beSrobert return !(__y < __x);
354*4bdff4beSrobert }
355*4bdff4beSrobert
356*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
357*4bdff4beSrobert friend constexpr bool operator>=(const __iterator& __x, const __iterator& __y)
358*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> {
359*4bdff4beSrobert return !(__x < __y);
360*4bdff4beSrobert }
361*4bdff4beSrobert
362*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
363*4bdff4beSrobert friend constexpr auto operator<=>(const __iterator& __x, const __iterator& __y)
364*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> &&
365*4bdff4beSrobert (three_way_comparable<iterator_t<__maybe_const<_Const, _Views>>> && ...) {
366*4bdff4beSrobert return __x.__current_ <=> __y.__current_;
367*4bdff4beSrobert }
368*4bdff4beSrobert
369*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
370*4bdff4beSrobert friend constexpr __iterator operator+(const __iterator& __i, difference_type __n)
371*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> {
372*4bdff4beSrobert auto __r = __i;
373*4bdff4beSrobert __r += __n;
374*4bdff4beSrobert return __r;
375*4bdff4beSrobert }
376*4bdff4beSrobert
377*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
378*4bdff4beSrobert friend constexpr __iterator operator+(difference_type __n, const __iterator& __i)
379*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> {
380*4bdff4beSrobert return __i + __n;
381*4bdff4beSrobert }
382*4bdff4beSrobert
383*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
384*4bdff4beSrobert friend constexpr __iterator operator-(const __iterator& __i, difference_type __n)
385*4bdff4beSrobert requires __zip_all_random_access<_Const, _Views...> {
386*4bdff4beSrobert auto __r = __i;
387*4bdff4beSrobert __r -= __n;
388*4bdff4beSrobert return __r;
389*4bdff4beSrobert }
390*4bdff4beSrobert
391*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
392*4bdff4beSrobert friend constexpr difference_type operator-(const __iterator& __x, const __iterator& __y)
393*4bdff4beSrobert requires(sized_sentinel_for<iterator_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_Const, _Views>>> &&
394*4bdff4beSrobert ...) {
395*4bdff4beSrobert const auto __diffs = ranges::__tuple_zip_transform(minus<>(), __x.__current_, __y.__current_);
396*4bdff4beSrobert return std::apply(
397*4bdff4beSrobert [](auto... __ds) {
398*4bdff4beSrobert return ranges::min({difference_type(__ds)...},
399*4bdff4beSrobert [](auto __a, auto __b) { return ranges::__abs(__a) < ranges::__abs(__b); });
400*4bdff4beSrobert },
401*4bdff4beSrobert __diffs);
402*4bdff4beSrobert }
403*4bdff4beSrobert
404*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
405*4bdff4beSrobert friend constexpr auto iter_move(const __iterator& __i) noexcept(
406*4bdff4beSrobert (noexcept(ranges::iter_move(std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) && ...) &&
407*4bdff4beSrobert (is_nothrow_move_constructible_v<range_rvalue_reference_t<__maybe_const<_Const, _Views>>> && ...)) {
408*4bdff4beSrobert return ranges::__tuple_transform(ranges::iter_move, __i.__current_);
409*4bdff4beSrobert }
410*4bdff4beSrobert
411*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
412*4bdff4beSrobert friend constexpr void iter_swap(const __iterator& __l, const __iterator& __r) noexcept(
413*4bdff4beSrobert (noexcept(ranges::iter_swap(std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>(),
414*4bdff4beSrobert std::declval<const iterator_t<__maybe_const<_Const, _Views>>&>())) &&
415*4bdff4beSrobert ...))
416*4bdff4beSrobert requires(indirectly_swappable<iterator_t<__maybe_const<_Const, _Views>>> && ...) {
417*4bdff4beSrobert ranges::__tuple_zip_for_each(ranges::iter_swap, __l.__current_, __r.__current_);
418*4bdff4beSrobert }
419*4bdff4beSrobert };
420*4bdff4beSrobert
421*4bdff4beSrobert template <input_range... _Views>
422*4bdff4beSrobert requires(view<_Views> && ...) && (sizeof...(_Views) > 0)
423*4bdff4beSrobert template <bool _Const>
424*4bdff4beSrobert class zip_view<_Views...>::__sentinel {
425*4bdff4beSrobert
426*4bdff4beSrobert __tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end_;
427*4bdff4beSrobert
428*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
429*4bdff4beSrobert constexpr explicit __sentinel(__tuple_or_pair<sentinel_t<__maybe_const<_Const, _Views>>...> __end) : __end_(__end) {}
430*4bdff4beSrobert
431*4bdff4beSrobert friend class zip_view<_Views...>;
432*4bdff4beSrobert
433*4bdff4beSrobert // hidden friend cannot access private member of iterator because they are friends of friends
434*4bdff4beSrobert template <bool _OtherConst>
435*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI static constexpr decltype(auto)
436*4bdff4beSrobert __iter_current(zip_view<_Views...>::__iterator<_OtherConst> const& __it) {
437*4bdff4beSrobert return (__it.__current_);
438*4bdff4beSrobert }
439*4bdff4beSrobert
440*4bdff4beSrobert public:
441*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
442*4bdff4beSrobert __sentinel() = default;
443*4bdff4beSrobert
444*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI
445*4bdff4beSrobert constexpr __sentinel(__sentinel<!_Const> __i)
446*4bdff4beSrobert requires _Const && (convertible_to<sentinel_t<_Views>, sentinel_t<__maybe_const<_Const, _Views>>> && ...)
447*4bdff4beSrobert : __end_(std::move(__i.__end_)) {}
448*4bdff4beSrobert
449*4bdff4beSrobert template <bool _OtherConst>
450*4bdff4beSrobert requires(sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_OtherConst, _Views>>> &&
451*4bdff4beSrobert ...)
452*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI friend constexpr bool operator==(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
453*4bdff4beSrobert return ranges::__tuple_any_equals(__iter_current(__x), __y.__end_);
454*4bdff4beSrobert }
455*4bdff4beSrobert
456*4bdff4beSrobert template <bool _OtherConst>
457*4bdff4beSrobert requires(
458*4bdff4beSrobert sized_sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_OtherConst, _Views>>> &&
459*4bdff4beSrobert ...)
460*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI friend constexpr common_type_t<range_difference_t<__maybe_const<_OtherConst, _Views>>...>
461*4bdff4beSrobert operator-(const __iterator<_OtherConst>& __x, const __sentinel& __y) {
462*4bdff4beSrobert const auto __diffs = ranges::__tuple_zip_transform(minus<>(), __iter_current(__x), __y.__end_);
463*4bdff4beSrobert return std::apply(
464*4bdff4beSrobert [](auto... __ds) {
465*4bdff4beSrobert using _Diff = common_type_t<range_difference_t<__maybe_const<_OtherConst, _Views>>...>;
466*4bdff4beSrobert return ranges::min({_Diff(__ds)...},
467*4bdff4beSrobert [](auto __a, auto __b) { return ranges::__abs(__a) < ranges::__abs(__b); });
468*4bdff4beSrobert },
469*4bdff4beSrobert __diffs);
470*4bdff4beSrobert }
471*4bdff4beSrobert
472*4bdff4beSrobert template <bool _OtherConst>
473*4bdff4beSrobert requires(
474*4bdff4beSrobert sized_sentinel_for<sentinel_t<__maybe_const<_Const, _Views>>, iterator_t<__maybe_const<_OtherConst, _Views>>> &&
475*4bdff4beSrobert ...)
476*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI friend constexpr common_type_t<range_difference_t<__maybe_const<_OtherConst, _Views>>...>
477*4bdff4beSrobert operator-(const __sentinel& __y, const __iterator<_OtherConst>& __x) {
478*4bdff4beSrobert return -(__x - __y);
479*4bdff4beSrobert }
480*4bdff4beSrobert };
481*4bdff4beSrobert
482*4bdff4beSrobert template <class... _Views>
483*4bdff4beSrobert inline constexpr bool enable_borrowed_range<zip_view<_Views...>> = (enable_borrowed_range<_Views> && ...);
484*4bdff4beSrobert
485*4bdff4beSrobert namespace views {
486*4bdff4beSrobert namespace __zip {
487*4bdff4beSrobert
488*4bdff4beSrobert struct __fn {
489*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr auto operator()() const noexcept { return empty_view<tuple<>>{}; }
490*4bdff4beSrobert
491*4bdff4beSrobert template <class... _Ranges>
492*4bdff4beSrobert _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Ranges&&... __rs) const
493*4bdff4beSrobert noexcept(noexcept(zip_view<all_t<_Ranges&&>...>(std::forward<_Ranges>(__rs)...)))
494*4bdff4beSrobert -> decltype(zip_view<all_t<_Ranges&&>...>(std::forward<_Ranges>(__rs)...)) {
495*4bdff4beSrobert return zip_view<all_t<_Ranges>...>(std::forward<_Ranges>(__rs)...);
496*4bdff4beSrobert }
497*4bdff4beSrobert };
498*4bdff4beSrobert
499*4bdff4beSrobert } // namespace __zip
500*4bdff4beSrobert inline namespace __cpo {
501*4bdff4beSrobert inline constexpr auto zip = __zip::__fn{};
502*4bdff4beSrobert } // namespace __cpo
503*4bdff4beSrobert } // namespace views
504*4bdff4beSrobert } // namespace ranges
505*4bdff4beSrobert
506*4bdff4beSrobert #endif // _LIBCPP_STD_VER > 20
507*4bdff4beSrobert
508*4bdff4beSrobert _LIBCPP_END_NAMESPACE_STD
509*4bdff4beSrobert
510*4bdff4beSrobert _LIBCPP_POP_MACROS
511*4bdff4beSrobert
512*4bdff4beSrobert #endif // _LIBCPP___RANGES_ZIP_VIEW_H
513