15 #ifndef RANGES_V3_VIEW_STRIDE_HPP
16 #define RANGES_V3_VIEW_STRIDE_HPP
18 #include <type_traits>
31 #include <range/v3/utility/static_const.hpp>
36 #include <range/v3/detail/prologue.hpp>
41 template<
typename Rng>
46 template<
typename Rng>
47 using stride_view_adaptor =
48 view_adaptor<stride_view<Rng>, Rng,
49 is_finite<Rng>::value ? finite : range_cardinality<Rng>::value>;
57 template<
typename Rng,
bool B
idiRange>
58 struct stride_view_base_;
59 template<
typename Rng>
60 using stride_view_base = stride_view_base_<Rng, (bool)bidirectional_range<Rng>>;
62 template<
typename Rng,
bool >
63 struct stride_view_base_ : stride_view_adaptor<Rng>
65 stride_view_base_() =
default;
66 constexpr stride_view_base_(Rng && rng, range_difference_t<Rng>
const stride)
67 : stride_view_adaptor<Rng>{std::move(rng)}
68 , stride_{(RANGES_EXPECT(0 < stride), stride)}
69 , offset_{calc_offset(
meta::bool_<sized_range<Rng>>{})}
73 constexpr
void set_offset(range_difference_t<Rng>
const delta) noexcept
75 RANGES_EXPECT(0 <= delta && delta < stride_);
79 RANGES_EXPECT(offset_ == delta);
81 constexpr
void set_offset(range_difference_t<Rng>
const)
const noexcept
83 constexpr range_difference_t<Rng> get_offset(
bool check =
true) const noexcept
85 RANGES_EXPECT(!check || 0 <= offset_);
89 range_difference_t<Rng> stride_;
90 range_difference_t<Rng> offset_ = -1;
93 constexpr range_difference_t<Rng> calc_offset(std::true_type)
95 if(
auto const rem = ranges::distance(this->base()) % stride_)
100 constexpr range_difference_t<Rng> calc_offset(std::false_type)
const noexcept
106 template<
typename Rng>
107 struct stride_view_base_<Rng, false> : stride_view_adaptor<Rng>
109 stride_view_base_() =
default;
110 constexpr stride_view_base_(Rng && rng, range_difference_t<Rng>
const stride)
111 : stride_view_adaptor<Rng>{std::move(rng)}
112 , stride_{(RANGES_EXPECT(0 < stride), stride)}
116 constexpr
void set_offset(range_difference_t<Rng>
const)
const noexcept
118 constexpr range_difference_t<Rng> get_offset(
bool =
true) const noexcept
123 range_difference_t<Rng> stride_;
130 template<
typename Rng>
139 static constexpr
bool const_iterable() noexcept
141 return range<Rng const> &&
142 (sized_range<Rng const> || !bidirectional_range<Rng const>);
151 static constexpr
bool can_bound() noexcept
153 using CRng = meta::const_if_c<Const, Rng>;
154 return common_range<CRng> &&
155 (sized_range<CRng> || !bidirectional_range<CRng>);
162 friend struct adaptor<!Const>;
163 using CRng = meta::const_if_c<Const, Rng>;
164 using stride_view_t = meta::const_if_c<Const, stride_view>;
165 stride_view_t * rng_;
169 constexpr adaptor(stride_view_t * rng) noexcept
172 template(
bool Other)(
173 requires Const AND CPP_NOT(Other))
174 adaptor(adaptor<Other> that)
179 auto const last = ranges::end(rng_->base());
180 RANGES_EXPECT(it != last);
181 auto const delta = ranges::advance(it, rng_->stride_, last);
184 rng_->set_offset(delta);
190 requires bidirectional_range<CRng>)
192 RANGES_EXPECT(it != ranges::begin(rng_->base()));
193 auto delta = -rng_->stride_;
194 if(it == ranges::end(rng_->base()))
196 RANGES_EXPECT(rng_->get_offset() >= 0);
197 delta += rng_->get_offset();
199 ranges::advance(it, delta);
201 template(
typename Other)(
203 constexpr range_difference_t<Rng> distance_to(
iterator_t<CRng> const & here,
204 Other
const & there)
const
206 range_difference_t<Rng> delta = there - here;
208 delta -= rng_->stride_ - 1;
210 delta += rng_->stride_ - 1;
211 return delta / rng_->stride_;
216 requires random_access_range<CRng>)
221 auto const last = ranges::end(rng_->base());
224 RANGES_EXPECT(n < 0);
225 RANGES_EXPECT(rng_->get_offset() >= 0);
226 n += rng_->get_offset();
230 auto delta = ranges::advance(it, n, last);
234 rng_->set_offset(delta % rng_->stride_);
240 ranges::advance(it, n);
242 auto const first = ranges::begin(rng_->base());
243 auto const delta = ranges::advance(it, n,
first);
244 RANGES_EXPECT(delta == 0);
249 constexpr adaptor<false> begin_adaptor() noexcept
251 return adaptor<false>{
this};
254 constexpr
auto begin_adaptor()
const noexcept
255 -> CPP_ret(adaptor<true>)(
256 requires(const_iterable()))
258 return adaptor<true>{
this};
261 constexpr meta::if_c<can_bound<false>(), adaptor<false>,
adaptor_base>
262 end_adaptor() noexcept
267 constexpr
auto end_adaptor()
const noexcept
268 -> CPP_ret(meta::if_c<can_bound<true>(), adaptor<true>,
adaptor_base>)(
269 requires (const_iterable()))
276 constexpr
stride_view(Rng rng, range_difference_t<Rng>
const stride)
277 : detail::stride_view_base<Rng>{std::move(rng), stride}
280 constexpr
auto CPP_fun(
size)()(
281 requires sized_range<Rng>)
283 using size_type = range_size_t<Rng>;
285 return (n +
static_cast<size_type
>(this->stride_) - 1) /
286 static_cast<size_type
>(this->stride_);
289 constexpr
auto CPP_fun(
size)()(
const
290 requires sized_range<Rng const>)
292 using size_type = range_size_t<Rng const>;
294 return (n +
static_cast<size_type
>(this->stride_) - 1) /
295 static_cast<size_type
>(this->stride_);
299 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
300 template<
typename Rng>
309 template(
typename Rng)(
310 requires viewable_range<Rng> AND input_range<Rng>)
312 operator()(Rng && rng, range_difference_t<Rng> step)
const
320 using stride_base_fn::operator();
322 template(
typename Difference)(
323 requires detail::integer_like_<Difference>)
324 constexpr
auto operator()(Difference step)
const
337 #include <range/v3/detail/epilogue.hpp>
338 #include <range/v3/detail/satisfy_boost_range.hpp>
CPP_concept sized_sentinel_for
\concept sized_sentinel_for
Definition: concepts.hpp:332
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< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
defer< bind_back, Fn, Ts... > bind_back
Definition: meta.hpp:994
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
Definition: adaptor.hpp:110
Definition: stride.hpp:132
Definition: stride.hpp:308
Definition: stride.hpp:319