Horizon
Loading...
Searching...
No Matches
intersperse.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Eric Niebler 2013-present
5//
6// Use, modification and distribution is subject to the
7// Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10//
11// Project home: https://github.com/ericniebler/range-v3
12//
13
14#ifndef RANGES_V3_VIEW_INTERSPERSE_HPP
15#define RANGES_V3_VIEW_INTERSPERSE_HPP
16
17#include <type_traits>
18#include <utility>
19
20#include <meta/meta.hpp>
21
23
30#include <range/v3/utility/static_const.hpp>
33
34#include <range/v3/detail/prologue.hpp>
35
36namespace ranges
37{
40 template<typename Rng>
42 : view_adaptor<intersperse_view<Rng>, Rng,
43 (range_cardinality<Rng>::value > 0)
44 ? static_cast<cardinality>(range_cardinality<Rng>::value * 2 - 1)
45 : range_cardinality<Rng>::value>
46 {
47 intersperse_view() = default;
48 constexpr intersperse_view(Rng rng, range_value_t<Rng> val)
49 : intersperse_view::view_adaptor{detail::move(rng)}
50 , val_(detail::move(val))
51 {}
52 CPP_auto_member
53 constexpr auto CPP_fun(size)()(const //
55 {
56 auto const n = ranges::size(this->base());
57 return n ? n * 2 - 1 : 0;
58 }
59 CPP_auto_member
60 constexpr auto CPP_fun(size)()(
61 requires sized_range<Rng>)
62 {
63 auto const n = ranges::size(this->base());
64 return n ? n * 2 - 1 : 0;
65 }
66
67 private:
68 friend range_access;
69 template<bool Const>
70 struct cursor_adaptor : adaptor_base
71 {
72 private:
73 friend struct cursor_adaptor<!Const>;
74 using CRng = meta::const_if_c<Const, Rng>;
75 bool toggle_ = false;
76 range_value_t<Rng> val_;
77
78 public:
79 cursor_adaptor() = default;
80 constexpr explicit cursor_adaptor(range_value_t<Rng> const & val)
81 : val_{val}
82 {}
83 template(bool Other)(
84 requires Const AND CPP_NOT(Other)) //
85 cursor_adaptor(cursor_adaptor<Other> that)
86 : toggle_(that.toggle_)
87 , val_(std::move(that.val_))
88 {}
89 template<typename View>
90 constexpr iterator_t<CRng> begin(View & view)
91 {
92 auto first = ranges::begin(view.base());
93 toggle_ = first != ranges::end(view.base());
94 return first;
95 }
96 constexpr range_value_t<Rng> read(iterator_t<CRng> const & it) const
97 {
98 return toggle_ ? *it : val_;
99 }
100 CPP_member
101 constexpr auto equal(iterator_t<CRng> const & it0,
102 iterator_t<CRng> const & it1,
103 cursor_adaptor const & other) const //
104 -> CPP_ret(bool)(
106 {
107 return it0 == it1 && toggle_ == other.toggle_;
108 }
109 constexpr void next(iterator_t<CRng> & it)
110 {
111 if(toggle_)
112 ++it;
113 toggle_ = !toggle_;
114 }
115 CPP_member
116 constexpr auto prev(iterator_t<CRng> & it) //
117 -> CPP_ret(void)(
119 {
120 toggle_ = !toggle_;
121 if(toggle_)
122 --it;
123 }
124 CPP_member
125 constexpr auto distance_to(iterator_t<CRng> const & it,
126 iterator_t<CRng> const & other_it,
127 cursor_adaptor const & other) const
128 -> CPP_ret(range_difference_t<Rng>)(
130 {
131 return (other_it - it) * 2 + (other.toggle_ - toggle_);
132 }
133 CPP_member
134 constexpr auto advance(iterator_t<CRng> & it, range_difference_t<CRng> n) //
135 -> CPP_ret(void)(
137 {
138 ranges::advance(it, n >= 0 ? (n + toggle_) / 2 : (n - !toggle_) / 2);
139 if(n % 2 != 0)
140 toggle_ = !toggle_;
141 }
142 };
143 template<bool Const>
144 struct sentinel_adaptor : adaptor_base
145 {
146 private:
147 using CRng = meta::const_if_c<Const, Rng>;
148
149 public:
150 sentinel_adaptor() = default;
151 template(bool Other)(
152 requires Const AND CPP_NOT(Other)) //
153 sentinel_adaptor(sentinel_adaptor<Other>)
154 {}
155 static constexpr bool empty(iterator_t<CRng> const & it,
156 cursor_adaptor<Const> const &,
157 sentinel_t<CRng> const & sent)
158 {
159 return it == sent;
160 }
161 };
162 constexpr cursor_adaptor<false> begin_adaptor()
163 {
164 return cursor_adaptor<false>{val_};
165 }
166 CPP_member
167 constexpr auto begin_adaptor() const //
168 -> CPP_ret(cursor_adaptor<true>)(
169 requires range<Rng const>)
170 {
171 return cursor_adaptor<true>{val_};
172 }
173 CPP_member
174 constexpr auto end_adaptor() //
175 -> CPP_ret(cursor_adaptor<false>)(
176 requires common_range<Rng> && (!single_pass_iterator_<iterator_t<Rng>>))
177 {
178 return cursor_adaptor<false>{val_};
179 }
180 CPP_member
181 constexpr auto end_adaptor() noexcept //
182 -> CPP_ret(sentinel_adaptor<false>)(
183 requires (!common_range<Rng>) || single_pass_iterator_<iterator_t<Rng>>)
184 {
185 return {};
186 }
187 template(bool Const = true)(
188 requires Const AND range<meta::const_if_c<Const, Rng>> AND
189 common_range<meta::const_if_c<Const, Rng>> AND
190 (!single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng>>>)) //
191 constexpr cursor_adaptor<Const> end_adaptor() const
192 {
193 return cursor_adaptor<true>{val_};
194 }
195 template(bool Const = true)(
196 requires Const AND range<meta::const_if_c<Const, Rng>> AND
197 (!common_range<meta::const_if_c<Const, Rng>> ||
198 single_pass_iterator_<iterator_t<meta::const_if_c<Const, Rng>>>)) //
199 constexpr sentinel_adaptor<Const> end_adaptor() const noexcept
200 {
201 return {};
202 }
203
204 range_value_t<Rng> val_;
205 };
206
207 template<typename Rng>
208 RANGES_INLINE_VAR constexpr bool enable_borrowed_range<intersperse_view<Rng>> = //
209 enable_borrowed_range<Rng>;
210
211#if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
212 template<typename Rng>
213 intersperse_view(Rng &&, range_value_t<Rng>)
215#endif
216
217 namespace views
218 {
220 {
221 template(typename Rng)(
223 convertible_to<range_reference_t<Rng>, range_value_t<Rng>> AND
224 semiregular<range_value_t<Rng>>)
225 constexpr intersperse_view<all_t<Rng>> //
226 operator()(Rng && rng, range_value_t<Rng> val) const
227 {
228 return {all(static_cast<Rng &&>(rng)), std::move(val)};
229 }
230 };
231
233 {
234 using intersperse_base_fn::operator();
235
236 template(typename T)(
237 requires copyable<T>)
238 constexpr auto operator()(T t) const
239 {
240 return make_view_closure(bind_back(intersperse_base_fn{}, std::move(t)));
241 }
242 };
243
246 RANGES_INLINE_VARIABLE(intersperse_fn, intersperse)
247 } // namespace views
248} // namespace ranges
249
250#include <range/v3/detail/epilogue.hpp>
251#include <range/v3/detail/satisfy_boost_range.hpp>
252RANGES_SATISFY_BOOST_RANGE(::ranges::intersperse_view)
253
254#endif
The bidirectional_range concept.
The common_range concept.
The input_range concept.
The random_access_range concept.
The range concept.
The sentinel_for concept.
The sized_range concept.
The sized_sentinel_for concept.
The viewable_range concept.
decltype(begin(declval(Rng &))) iterator_t
Definition access.hpp:698
Tiny meta-programming library.
Definition adaptor.hpp:110
Definition intersperse.hpp:46
Definition traits.hpp:128
Definition adaptor.hpp:475
Definition intersperse.hpp:220
Definition intersperse.hpp:233