14#ifndef RANGES_V3_VIEW_CONCAT_HPP
15#define RANGES_V3_VIEW_CONCAT_HPP
32#include <range/v3/utility/static_const.hpp>
39#include <range/v3/detail/prologue.hpp>
46 template<
typename State,
typename Value>
47 using concat_cardinality_ = std::integral_constant<
49 State::value == infinite || Value::value == infinite
51 : State::value == unknown || Value::value == unknown
53 : State::value == finite || Value::value == finite
55 :
static_cast<cardinality
>(State::value + Value::value)>;
57 template<
typename... Rngs>
58 using concat_cardinality =
60 std::integral_constant<cardinality, static_cast<cardinality>(0)>,
67 template<
typename... Rngs>
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);
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_)));
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);
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);
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
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); }),
392#if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
393 template<
typename... Rng>
402 template(
typename... Rngs)(
404 concat_view<all_t<Rngs>...>
operator()(Rngs &&... rngs)
const
408 template(
typename Rng)(
410 all_t<Rng> operator()(Rng && rng)
const
412 return all(
static_cast<Rng &&
>(rng));
416 template(
typename Rng0,
typename Rng1)(
423 all(
static_cast<Rng0 &&
>(rng0)),
424 all(
static_cast<Rng1 &&
>(rng1))};
426 template(
typename Rng0,
typename Rng1,
typename Rng2)(
431 operator()(Rng0 && rng0, Rng1 && rng1, Rng2 && rng2)
const
434 all(
static_cast<Rng0 &&
>(rng0)),
435 all(
static_cast<Rng1 &&
>(rng1)),
436 all(
static_cast<Rng2 &&
>(rng2))};
448#include <range/v3/detail/epilogue.hpp>
449#include <range/v3/detail/satisfy_boost_range.hpp>
The bidirectional_iterator concept.
The common_range concept.
The random_access_iterator concept.
The viewable_range concept.
decltype(begin(declval(Rng &))) iterator_t
Definition: access.hpp:698
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector > >, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition: meta.hpp:163
front< Pair > first
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2251
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
_t< detail::back_< L > > back
Return the last element in meta::list L.
Definition: meta.hpp:2103
_t< detail::_if_< list< Args... > > > if_
Select one type or another depending on a compile-time Boolean.
Definition: meta.hpp:1247
Definition: range_fwd.hpp:488
Definition: concat.hpp:70
Definition: arithmetic.hpp:66
Definition: range_fwd.hpp:490
Definition: variant.hpp:71
Definition: arithmetic.hpp:25
Definition: variant.hpp:621
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition: facade.hpp:66
Definition: concat.hpp:401