Horizon
Loading...
Searching...
No Matches
cycle.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Eric Niebler 2013-present
5// Copyright Gonzalo Brito Gadeschi 2015
6// Copyright Casey Carter 2015
7//
8// Use, modification and distribution is subject to the
9// Boost Software License, Version 1.0. (See accompanying
10// file LICENSE_1_0.txt or copy at
11// http://www.boost.org/LICENSE_1_0.txt)
12//
13// Project home: https://github.com/ericniebler/range-v3
14//
15
16#ifndef RANGES_V3_VIEW_CYCLE_HPP
17#define RANGES_V3_VIEW_CYCLE_HPP
18
19#include <type_traits>
20#include <utility>
21
22#include <meta/meta.hpp>
23
25
35#include <range/v3/utility/static_const.hpp>
36#include <range/v3/view/all.hpp>
39
40#include <range/v3/detail/prologue.hpp>
41
42namespace ranges
43{
46 template<typename Rng, bool /* = (bool) is_infinite<Rng>() */>
47 struct RANGES_EMPTY_BASES cycled_view
48 : view_facade<cycled_view<Rng>, infinite>
49 , private detail::non_propagating_cache<iterator_t<Rng>, cycled_view<Rng>,
50 !common_range<Rng>>
51 {
52 private:
53 CPP_assert(forward_range<Rng> && !is_infinite<Rng>::value);
54 friend range_access;
55 Rng rng_;
56
57 using cache_t = detail::non_propagating_cache<iterator_t<Rng>, cycled_view<Rng>,
59
60 template<bool IsConst>
61 struct cursor
62 {
63 private:
64 friend struct cursor<!IsConst>;
65 template<typename T>
66 using constify_if = meta::const_if_c<IsConst, T>;
67 using cycled_view_t = constify_if<cycled_view>;
68 using CRng = constify_if<Rng>;
69 using iterator = iterator_t<CRng>;
70
71 cycled_view_t * rng_{};
72 iterator it_{};
73 std::intmax_t n_ = 0;
74
75 iterator get_end_(std::true_type, bool = false) const
76 {
77 return ranges::end(rng_->rng_);
78 }
79 template<bool CanBeEmpty = false>
80 iterator get_end_(std::false_type, meta::bool_<CanBeEmpty> = {}) const
81 {
82 auto & end_ = static_cast<cache_t &>(*rng_);
83 RANGES_EXPECT(CanBeEmpty || end_);
84 if(CanBeEmpty && !end_)
85 end_ = ranges::next(it_, ranges::end(rng_->rng_));
86 return *end_;
87 }
88 void set_end_(std::true_type) const
89 {}
90 void set_end_(std::false_type) const
91 {
92 auto & end_ = static_cast<cache_t &>(*rng_);
93 if(!end_)
94 end_ = it_;
95 }
96
97 public:
98 cursor() = default;
99 cursor(cycled_view_t * rng)
100 : rng_(rng)
101 , it_(ranges::begin(rng->rng_))
102 {}
103 template(bool Other)(
104 requires IsConst AND CPP_NOT(Other)) //
105 cursor(cursor<Other> that)
106 : rng_(that.rng_)
107 , it_(std::move(that.it_))
108 {}
109 // clang-format off
110 auto CPP_auto_fun(read)()(const)
111 (
112 return *it_
113 )
114 // clang-format on
115 CPP_member
116 auto equal(cursor const & pos) const //
117 -> CPP_ret(bool)(
118 requires equality_comparable<iterator>)
119 {
120 RANGES_EXPECT(rng_ == pos.rng_);
121 return n_ == pos.n_ && it_ == pos.it_;
122 }
123 void next()
124 {
125 auto const last = ranges::end(rng_->rng_);
126 RANGES_EXPECT(it_ != last);
127 if(++it_ == last)
128 {
129 ++n_;
130 this->set_end_(meta::bool_<(bool)common_range<CRng>>{});
131 it_ = ranges::begin(rng_->rng_);
132 }
133 }
134 CPP_member
135 auto prev() //
136 -> CPP_ret(void)(
138 {
139 if(it_ == ranges::begin(rng_->rng_))
140 {
141 RANGES_EXPECT(n_ > 0); // decrementing the begin iterator?!
142 --n_;
143 it_ = this->get_end_(meta::bool_<(bool)common_range<CRng>>{});
144 }
145 --it_;
146 }
147 template(typename Diff)(
148 requires random_access_range<CRng> AND
149 detail::integer_like_<Diff>)
150 void advance(Diff n)
151 {
152 auto const first = ranges::begin(rng_->rng_);
153 auto const last = this->get_end_(meta::bool_<(bool)common_range<CRng>>{},
155 auto const dist = last - first;
156 auto const d = it_ - first;
157 auto const off = (d + n) % dist;
158 n_ += (d + n) / dist;
159 RANGES_EXPECT(n_ >= 0);
160 using D = range_difference_t<Rng>;
161 it_ = first + static_cast<D>(off < 0 ? off + dist : off);
162 }
163 CPP_auto_member
164 auto CPP_fun(distance_to)(cursor const & that)(const //
166 {
167 RANGES_EXPECT(that.rng_ == rng_);
168 auto const first = ranges::begin(rng_->rng_);
169 auto const last = this->get_end_(meta::bool_<(bool)common_range<Rng>>{},
171 auto const dist = last - first;
172 return (that.n_ - n_) * dist + (that.it_ - it_);
173 }
174 };
175
176 CPP_member
177 auto begin_cursor() //
178 -> CPP_ret(cursor<false>)(
179 requires (!simple_view<Rng>() || !common_range<Rng const>))
180 {
181 return {this};
182 }
183 CPP_member
184 auto begin_cursor() const //
185 -> CPP_ret(cursor<true>)(
187 {
188 return {this};
189 }
190 unreachable_sentinel_t end_cursor() const
191 {
192 return unreachable;
193 }
194
195 public:
196 cycled_view() = default;
198 explicit cycled_view(Rng rng)
199 : rng_(std::move(rng))
200 {
201 RANGES_EXPECT(!ranges::empty(rng_));
202 }
203 };
204
205 template<typename Rng>
207 {
208 CPP_assert(is_infinite<Rng>::value);
209 using identity_adaptor<Rng>::identity_adaptor;
210 };
211
212#if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
213 template<typename Rng>
214 cycled_view(Rng &&) //
216#endif
217
218 namespace views
219 {
222 struct cycle_fn
223 {
225 template(typename Rng)(
227 cycled_view<all_t<Rng>> operator()(Rng && rng) const
228 {
229 return cycled_view<all_t<Rng>>{all(static_cast<Rng &&>(rng))};
230 }
231 };
232
235 RANGES_INLINE_VARIABLE(view_closure<cycle_fn>, cycle)
236 } // namespace views
238} // namespace ranges
239
240#include <range/v3/detail/epilogue.hpp>
241
242#include <range/v3/detail/satisfy_boost_range.hpp>
243RANGES_SATISFY_BOOST_RANGE(::ranges::cycled_view)
244
245#endif
The bidirectional_range concept.
The common_range concept.
The forward_range concept.
The random_access_range concept.
The sized_sentinel_for concept.
The viewable_range concept.
decltype(begin(declval(Rng &))) iterator_t
Definition access.hpp:698
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition meta.hpp:168
Tiny meta-programming library.
Definition cycle.hpp:51
cycled_view(Rng rng)
Definition cycle.hpp:198
Definition all.hpp:96
Definition unreachable_sentinel.hpp:27
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition facade.hpp:66
Returns an infinite range that endlessly repeats the source range.
Definition cycle.hpp:223