69 :
view_facade<concat_view<Rngs...>, detail::concat_cardinality<Rngs...>::value>
73 using difference_type_ = common_type_t<range_difference_t<Rngs>...>;
74 static constexpr std::size_t cranges{
sizeof...(Rngs)};
75 std::tuple<Rngs...> rngs_;
77 template<
bool IsConst>
80 template<
bool IsConst>
84 friend struct sentinel<!IsConst>;
85 friend struct cursor<IsConst>;
87 using constify_if = meta::const_if_c<IsConst, T>;
88 using concat_view_t = constify_if<concat_view>;
93 sentinel(concat_view_t * rng,
end_tag)
94 : end_(end(std::get<cranges - 1>(rng->rngs_)))
97 requires IsConst AND CPP_NOT(Other))
98 sentinel(sentinel<Other> that)
99 : end_(std::move(that.end_))
103 template<
bool IsConst>
106 using difference_type = common_type_t<range_difference_t<Rngs>...>;
109 friend struct cursor<!IsConst>;
111 using constify_if = meta::const_if_c<IsConst, T>;
112 using concat_view_t = constify_if<concat_view>;
113 concat_view_t * rng_;
116 template<std::
size_t N>
119 RANGES_EXPECT(its_.index() == N);
120 if(ranges::get<N>(its_) == end(std::get<N>(rng_->rngs_)))
122 ranges::emplace<N + 1>(its_, begin(std::get<N + 1>(rng_->rngs_)));
128 RANGES_EXPECT(its_.index() == cranges - 1);
133 template(
typename I, std::size_t N)(
137 RANGES_ASSERT(it.get() != end(std::get<N>(pos->rng_->rngs_)));
145 template(
typename I)(
149 RANGES_ASSERT(it.get() != begin(std::get<0>(pos->rng_->rngs_)));
152 template(
typename I, std::size_t N)(
156 if(it.get() == begin(std::get<N>(pos->rng_->rngs_)))
158 auto && rng = std::get<N - 1>(pos->rng_->rngs_);
159 ranges::emplace<N - 1>(
161 ranges::next(ranges::begin(rng), ranges::end(rng)));
162 pos->its_.visit_i(*
this);
168 struct advance_fwd_fun
172 template(
typename I)(
176 ranges::advance(it.get(), n);
178 template(
typename I, std::size_t N)(
182 auto last = ranges::end(std::get<N>(pos->rng_->rngs_));
187 auto rest = ranges::advance(it.get(), n, std::move(last));
190 pos->its_.visit_i(advance_fwd_fun{pos, rest});
193 struct advance_rev_fun
197 template(
typename I)(
201 ranges::advance(it.get(), n);
203 template(
typename I, std::size_t N)(
207 auto first = ranges::begin(std::get<N>(pos->rng_->rngs_));
208 if(it.get() == first)
210 auto && rng = std::get<N - 1>(pos->rng_->rngs_);
211 ranges::emplace<N - 1>(
213 ranges::next(ranges::begin(rng), ranges::end(rng)));
214 pos->its_.visit_i(*
this);
218 auto rest = ranges::advance(it.get(), n, std::move(first));
220 pos->its_.visit_i(advance_rev_fun{pos, rest});
228 RANGES_EXPECT(
false);
230 template<std::
size_t N>
231 static difference_type distance_to_(
meta::size_t<N>, cursor
const & from,
234 if(from.its_.index() > N)
236 if(from.its_.index() == N)
238 if(to.its_.index() == N)
239 return distance(ranges::get<N>(from.its_),
240 ranges::get<N>(to.its_));
241 return distance(ranges::get<N>(from.its_),
242 end(std::get<N>(from.rng_->rngs_))) +
245 if(from.its_.index() < N && to.its_.index() > N)
246 return distance(std::get<N>(from.rng_->rngs_)) +
248 RANGES_EXPECT(to.its_.index() == N);
249 return distance(begin(std::get<N>(from.rng_->rngs_)),
250 ranges::get<N>(to.its_));
255 using reference = common_reference_t<range_reference_t<constify_if<Rngs>>...>;
260 , its_{emplaced_index<0>, begin(std::get<0>(rng->rngs_))}
264 cursor(concat_view_t * rng,
end_tag)
266 , its_{emplaced_index<cranges - 1>, end(std::get<cranges - 1>(rng->rngs_))}
268 template(
bool Other)(
269 requires IsConst && CPP_NOT(Other))
270 cursor(cursor<Other> that)
272 , its_(std::move(that.its_))
274 reference read()
const
277 return ranges::get<0>(unique_variant(its_.visit(
282 its_.visit_i(next_fun{
this});
285 auto equal(cursor
const & pos)
const
288 equality_comparable<variant<iterator_t<constify_if<Rngs>>...>>)
290 return its_ == pos.its_;
292 bool equal(sentinel<IsConst>
const & pos)
const
294 return its_.index() == cranges - 1 &&
295 ranges::get<cranges - 1>(its_) == pos.end_;
300 requires and_v<bidirectional_range<Rngs>...>)
302 its_.visit_i(prev_fun{
this});
305 auto advance(difference_type n)
307 requires and_v<random_access_range<Rngs>...>)
310 its_.visit_i(advance_fwd_fun{
this, n});
312 its_.visit_i(advance_rev_fun{
this, n});
315 auto distance_to(cursor
const & that)
const
316 -> CPP_ret(difference_type)(
317 requires and_v<sized_sentinel_for<iterator_t<Rngs>,
320 if(its_.index() <= that.its_.index())
325 cursor<meta::and_c<simple_view<Rngs>()...>::value> begin_cursor()
330 cursor<
meta::and_c<simple_view<Rngs>()...>::value>,
331 sentinel<meta::and_c<simple_view<Rngs>()...>::value>>
337 auto begin_cursor()
const
338 -> CPP_ret(cursor<true>)(
339 requires and_v<range<Rngs const>...>)
344 auto end_cursor()
const
349 requires and_v<range<Rngs const>...>)
357 : rngs_{std::move(rngs)...}
360 constexpr auto size()
const
361 -> CPP_ret(std::size_t)(
362 requires (detail::concat_cardinality<Rngs...>::value >= 0))
364 return static_cast<std::size_t
>(detail::concat_cardinality<Rngs...>::value);
367 constexpr auto CPP_fun(size)()(
const
368 requires(detail::concat_cardinality<Rngs...>::value < 0) &&
369 and_v<sized_range<Rngs const>...>)
371 using size_type = common_type_t<range_size_t<Rngs const>...>;
373 tuple_transform(rngs_,
374 [](
auto && r) -> size_type {
return ranges::size(r); }),
379 constexpr auto CPP_fun(size)()(
380 requires (detail::concat_cardinality<Rngs...>::value < 0) &&
381 and_v<sized_range<Rngs>...>)
383 using size_type = common_type_t<range_size_t<Rngs>...>;
385 tuple_transform(rngs_,
386 [](
auto && r) -> size_type {
return ranges::size(r); }),