Horizon
intersperse.hpp
Go to the documentation of this file.
1 // 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 
22 #include <range/v3/range_fwd.hpp>
23 
30 #include <range/v3/utility/static_const.hpp>
32 #include <range/v3/view/view.hpp>
33 
34 #include <range/v3/detail/prologue.hpp>
35 
36 namespace 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 //
54  requires sized_range<Rng 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)(
105  requires sentinel_for<iterator_t<CRng>, iterator_t<CRng>>)
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)(
118  requires bidirectional_range<CRng>)
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>)(
129  requires sized_sentinel_for<iterator_t<CRng>, iterator_t<CRng>>)
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)(
136  requires random_access_range<CRng>)
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)(
222  requires viewable_range<Rng> AND input_range<Rng> AND
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 
247  } // namespace views
248 } // namespace ranges
249 
250 #include <range/v3/detail/epilogue.hpp>
251 #include <range/v3/detail/satisfy_boost_range.hpp>
252 RANGES_SATISFY_BOOST_RANGE(::ranges::intersperse_view)
253 
254 #endif
CPP_concept common_range
\concept common_range
Definition: concepts.hpp:180
CPP_concept range
\concept range
Definition: concepts.hpp:69
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
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
bool_< 0==size< L >::type::value > empty
An Boolean integral constant wrapper around true if L is an empty type list; false,...
Definition: meta.hpp:2231
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