164 meta::fold<meta::list<range_cardinality<Rngs>...>,
165 std::integral_constant<cardinality, cardinality::infinite>,
166 meta::quote<detail::zip_cardinality>>::value>
169 CPP_assert(
sizeof...(Rngs) != 0);
172 semiregular_box_t<Fun> fun_;
173 std::tuple<Rngs...> rngs_;
174 using difference_type_ = common_type_t<range_difference_t<Rngs>...>;
183 friend struct cursor<Const>;
184 friend struct sentinel<!Const>;
185 std::tuple<sentinel_t<meta::const_if_c<Const, Rngs>>...> ends_;
188 sentinel() =
default;
189 sentinel(detail::ignore_t,
190 std::tuple<sentinel_t<meta::const_if_c<Const, Rngs>>...> ends)
191 : ends_(std::move(ends))
193 template(
bool Other)(
194 requires Const AND CPP_NOT(Other))
195 sentinel(sentinel<Other> that)
196 : ends_(std::move(that.ends_))
204 friend struct cursor<!Const>;
205 using fun_ref_ = semiregular_box_ref_or_val_t<Fun, Const>;
207 std::tuple<iterator_t<meta::const_if_c<Const, Rngs>>...> its_;
210 using difference_type =
211 common_type_t<range_difference_t<meta::const_if_c<Const, Rngs>>...>;
213 bool)single_pass_iterator_<
iterator_t<meta::const_if_c<Const, Rngs>>>...>;
214 using value_type = detail::decay_t<invoke_result_t<
219 std::tuple<
iterator_t<meta::const_if_c<Const, Rngs>>...> its)
220 : fun_(std::move(fun))
221 , its_(std::move(its))
223 template(
bool Other)(
224 requires Const AND CPP_NOT(Other))
225 cursor(cursor<Other> that)
226 : fun_(std::move(that.fun_))
227 , its_(std::move(that.its_))
230 auto CPP_auto_fun(read)()(
const)
232 return tuple_apply(fun_, its_)
237 tuple_for_each(its_, detail::inc);
240 auto equal(cursor
const & that)
const
249 return tuple_foldl(tuple_transform(its_, that.its_, detail::equal_to),
251 [](
bool a,
bool b) { return a || b; });
253 bool equal(sentinel<Const>
const & s)
const
258 return tuple_foldl(tuple_transform(its_, s.ends_, detail::equal_to),
260 [](
bool a,
bool b) { return a || b; });
265 requires and_v<bidirectional_range<meta::const_if_c<Const, Rngs>>...>)
267 tuple_for_each(its_, detail::dec);
270 auto advance(difference_type n)
272 requires and_v<random_access_range<meta::const_if_c<Const, Rngs>>...>)
274 tuple_for_each(its_, bind_back(detail::advance_, n));
277 auto distance_to(cursor
const & that)
const
278 -> CPP_ret(difference_type)(
285 if(0 < std::get<0>(that.its_) - std::get<0>(its_))
287 tuple_transform(its_, that.its_, detail::distance_to),
288 (std::numeric_limits<difference_type>::max)(),
292 tuple_transform(its_, that.its_, detail::distance_to),
293 (std::numeric_limits<difference_type>::min)(),
297 template<std::size_t... Is>
300 return invoke(fun_,
move_tag{}, std::get<Is>(its_)...)
303 auto move()
const noexcept(
noexcept(std::declval<cursor const &>().move_(
305 ->
decltype(std::declval<cursor const &>().move_(
315 !(
bool)single_pass_iterator_<iterator_t<Rngs>>...>,
316 cursor<Const>, sentinel<Const>>;
318 cursor<false> begin_cursor()
320 return {fun_, tuple_transform(rngs_, ranges::begin)};
322 end_cursor_t<false> end_cursor()
324 return {fun_, tuple_transform(rngs_, ranges::end)};
326 template(
bool Const =
true)(
329 cursor<Const> begin_cursor()
const
331 return {fun_, tuple_transform(rngs_, ranges::begin)};
333 template(
bool Const =
true)(
336 end_cursor_t<Const> end_cursor()
const
338 return {fun_, tuple_transform(rngs_, ranges::end)};
345 , rngs_{std::move(rngs)...}
348 : fun_(std::move(fun))
349 , rngs_{std::move(rngs)...}
352 constexpr auto CPP_fun(size)()(
const
355 using size_type = common_type_t<range_size_t<Rngs const>...>;
359 : tuple_foldl(tuple_transform(rngs_,
360 [](
auto && r) -> size_type {
361 return ranges::size(r);
363 (std::numeric_limits<size_type>::max)(),