Horizon
move_iterators.hpp
Go to the documentation of this file.
1 // Range v3 library
3 //
4 // Copyright Eric Niebler 2014-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 #ifndef RANGES_V3_ITERATOR_MOVE_ITERATORS_HPP
14 #define RANGES_V3_ITERATOR_MOVE_ITERATORS_HPP
15 
16 #include <cstddef>
17 #include <utility>
18 
19 #include <range/v3/range_fwd.hpp>
20 
24 
25 #include <range/v3/detail/prologue.hpp>
26 
27 namespace ranges
28 {
31  template<typename I>
33  {
34  private:
35  CPP_assert(input_iterator<I>);
36  I current_ = I{};
37 
38  public:
39  using iterator_type = I;
40  using difference_type = iter_difference_t<I>;
41  using value_type = iter_value_t<I>;
42  using iterator_category = std::input_iterator_tag;
43  using reference = iter_rvalue_reference_t<I>;
44 
45  constexpr move_iterator() = default;
46  explicit move_iterator(I i)
47  : current_(i)
48  {}
49  template(typename O)(
50  requires convertible_to<O, I>)
52  : current_(i.base())
53  {}
54  template(typename O)(
55  requires convertible_to<O, I>)
56  move_iterator & operator=(move_iterator<O> const & i)
57  {
58  current_ = i.base();
59  return *this;
60  }
61  I base() const
62  {
63  return current_;
64  }
65  // clang-format off
66  auto CPP_auto_fun(operator*)()(const)
67  (
68  return iter_move(current_)
69  )
70  // clang-format on
72  operator++()
73  {
74  ++current_;
75  return *this;
76  }
77  CPP_member
78  auto operator++(int) //
79  -> CPP_ret(void)(
80  requires (!forward_iterator<I>))
81  {
82  ++current_;
83  }
84  CPP_member
85  auto operator++(int) //
86  -> CPP_ret(move_iterator)(
87  requires forward_iterator<I>)
88  {
89  return move_iterator(current_++);
90  }
91  CPP_member
92  auto operator--() //
93  -> CPP_ret(move_iterator &)(
94  requires forward_iterator<I>)
95  {
96  --current_;
97  return *this;
98  }
99  CPP_member
100  auto operator--(int) //
101  -> CPP_ret(move_iterator)(
102  requires bidirectional_iterator<I>)
103  {
104  return move_iterator(current_--);
105  }
106  CPP_member
107  auto operator+(difference_type n) const //
108  -> CPP_ret(move_iterator)(
109  requires random_access_iterator<I>)
110  {
111  return move_iterator(current_ + n);
112  }
113  CPP_member
114  auto operator+=(difference_type n)
115  -> CPP_ret(move_iterator &)(
116  requires random_access_iterator<I>)
117  {
118  current_ += n;
119  return *this;
120  }
121  CPP_member
122  auto operator-(difference_type n) const //
123  -> CPP_ret(move_iterator)(
124  requires random_access_iterator<I>)
125  {
126  return move_iterator(current_ - n);
127  }
128  CPP_member
129  auto operator-=(difference_type n) //
130  -> CPP_ret(move_iterator &)(
131  requires random_access_iterator<I>)
132  {
133  current_ -= n;
134  return *this;
135  }
136  CPP_member
137  auto operator[](difference_type n) const //
138  -> CPP_ret(reference)(
139  requires random_access_iterator<I>)
140  {
141  return iter_move(current_ + n);
142  }
143 
144  template<typename I2>
145  friend auto operator==(move_iterator const & x, move_iterator<I2> const & y)
146  -> CPP_broken_friend_ret(bool)(
147  requires equality_comparable_with<I, I2>)
148  {
149  return x.base() == y.base();
150  }
151  template<typename I2>
152  friend auto operator!=(move_iterator const & x, move_iterator<I2> const & y)
153  -> CPP_broken_friend_ret(bool)(
154  requires equality_comparable_with<I, I2>)
155  {
156  return !(x == y);
157  }
158  template<typename I2>
159  friend auto operator<(move_iterator const & x, move_iterator<I2> const & y)
160  -> CPP_broken_friend_ret(bool)(
161  requires totally_ordered_with<I, I2>)
162  {
163  return x.base() < y.base();
164  }
165  template<typename I2>
166  friend auto operator<=(move_iterator const & x, move_iterator<I2> const & y)
167  -> CPP_broken_friend_ret(bool)(
168  requires totally_ordered_with<I, I2>)
169  {
170  return !(y < x);
171  }
172  template<typename I2>
173  friend auto operator>(move_iterator const & x, move_iterator<I2> const & y)
174  -> CPP_broken_friend_ret(bool)(
175  requires totally_ordered_with<I, I2>)
176  {
177  return y < x;
178  }
179  template<typename I2>
180  friend auto operator>=(move_iterator const & x, move_iterator<I2> const & y)
181  -> CPP_broken_friend_ret(bool)(
182  requires totally_ordered_with<I, I2>)
183  {
184  return !(x < y);
185  }
186 
187  template<typename I2>
188  friend auto operator-(move_iterator const & x, move_iterator<I2> const & y)
189  -> CPP_broken_friend_ret(iter_difference_t<I2>)(
190  requires sized_sentinel_for<I, I2>)
191  {
192  return x.base() - y.base();
193  }
195  friend auto operator+(iter_difference_t<I> n,
196  move_iterator const & x)
197  -> CPP_broken_friend_ret(move_iterator)(
198  requires random_access_iterator<I>)
199  {
200  return x + n;
201  }
202  };
203 
205  {
206  template(typename I)(
207  requires input_iterator<I>)
208  constexpr move_iterator<I> operator()(I it) const
209  {
210  return move_iterator<I>{detail::move(it)};
211  }
212  };
213 
214  RANGES_INLINE_VARIABLE(make_move_iterator_fn, make_move_iterator)
215 
216  template<typename S>
218  {
219  private:
220  S sent_;
221 
222  public:
223  constexpr move_sentinel()
224  : sent_{}
225  {}
226  constexpr explicit move_sentinel(S s)
227  : sent_(detail::move(s))
228  {}
229  template(typename OS)(
230  requires convertible_to<OS, S>)
231  constexpr explicit move_sentinel(move_sentinel<OS> const & that)
232  : sent_(that.base())
233  {}
234  template(typename OS)(
235  requires convertible_to<OS, S>)
236  move_sentinel & operator=(move_sentinel<OS> const & that)
237  {
238  sent_ = that.base();
239  return *this;
240  }
241  S base() const
242  {
243  return sent_;
244  }
245 
246  template<typename I>
247  friend auto operator==(move_iterator<I> const & i, move_sentinel const & s)
248  -> CPP_broken_friend_ret(bool)(
249  requires sentinel_for<S, I>)
250  {
251  return i.base() == s.base();
252  }
253  template<typename I>
254  friend auto operator==(move_sentinel const & s, move_iterator<I> const & i)
255  -> CPP_broken_friend_ret(bool)(
256  requires sentinel_for<S, I>)
257  {
258  return s.base() == i.base();
259  }
260  template<typename I>
261  friend auto operator!=(move_iterator<I> const & i, move_sentinel const & s)
262  -> CPP_broken_friend_ret(bool)(
263  requires sentinel_for<S, I>)
264  {
265  return i.base() != s.base();
266  }
267  template<typename I>
268  friend auto operator!=(move_sentinel const & s, move_iterator<I> const & i)
269  -> CPP_broken_friend_ret(bool)(
270  requires sentinel_for<S, I>)
271  {
272  return s.base() != i.base();
273  }
274  };
275 
277  {
278  template(typename I)(
279  requires input_iterator<I>)
280  constexpr move_iterator<I> operator()(I i) const
281  {
282  return move_iterator<I>{detail::move(i)};
283  }
284 
285  template(typename S)(
286  requires semiregular<S> AND (!input_iterator<S>)) //
287  constexpr move_sentinel<S> operator()(S s) const
288  {
289  return move_sentinel<S>{detail::move(s)};
290  }
291  };
292 
293  RANGES_INLINE_VARIABLE(make_move_sentinel_fn, make_move_sentinel)
294 
295 
296  namespace detail
297  {
298  template<typename I, bool IsReadable>
299  struct move_into_cursor_types_
300  {};
301 
302  template<typename I>
303  struct move_into_cursor_types_<I, true>
304  {
305  using value_type = iter_value_t<I>;
306  using single_pass = meta::bool_<(bool)single_pass_iterator_<I>>;
307  };
308 
309  template<typename I>
310  using move_into_cursor_types =
311  move_into_cursor_types_<I, (bool)indirectly_readable<I>>;
312 
313  template<typename I>
314  struct move_into_cursor : move_into_cursor_types<I>
315  {
316  private:
317  friend range_access;
318  struct mixin : basic_mixin<move_into_cursor>
319  {
320  mixin() = default;
321  #ifndef _MSC_VER
322  using basic_mixin<move_into_cursor>::basic_mixin;
323  #else
324  constexpr explicit mixin(move_into_cursor && cur)
325  : basic_mixin<move_into_cursor>(static_cast<move_into_cursor &&>(cur))
326  {}
327  constexpr explicit mixin(move_into_cursor const & cur)
328  : basic_mixin<move_into_cursor>(cur)
329  {}
330  #endif
331  explicit mixin(I it)
332  : mixin{move_into_cursor{std::move(it)}}
333  {}
334  I base() const
335  {
336  return this->get().it_;
337  }
338  };
339 
340  I it_ = I();
341 
342  explicit move_into_cursor(I it)
343  : it_(std::move(it))
344  {}
345  void next()
346  {
347  ++it_;
348  }
349  template(typename T)(
350  requires indirectly_writable<I, aux::move_t<T>>)
351  void write(T && t) noexcept(noexcept(*it_ = std::move(t)))
352  {
353  *it_ = std::move(t);
354  }
355  template(typename T)(
356  requires indirectly_writable<I, aux::move_t<T>>)
357  void write(T && t) const noexcept(noexcept(*it_ = std::move(t)))
358  {
359  *it_ = std::move(t);
360  }
361  CPP_member
362  auto read() const noexcept(noexcept(*std::declval<I const &>()))
363  -> CPP_ret(iter_reference_t<I>)(
364  requires indirectly_readable<I>)
365  {
366  return *it_;
367  }
368  CPP_member
369  auto equal(move_into_cursor const & that) const //
370  -> CPP_ret(bool)(
371  requires input_iterator<I>)
372  {
373  return it_ == that.it_;
374  }
375  CPP_member
376  auto prev() //
377  -> CPP_ret(void)(
378  requires bidirectional_iterator<I>)
379  {
380  --it_;
381  }
382  CPP_member
383  auto advance(iter_difference_t<I> n) //
384  -> CPP_ret(void)(
385  requires random_access_iterator<I>)
386  {
387  it_ += n;
388  }
389  CPP_member
390  auto distance_to(move_into_cursor const & that) const //
391  -> CPP_ret(iter_difference_t<I>)(
392  requires sized_sentinel_for<I, I>)
393  {
394  return that.it_ - it_;
395  }
396  template(typename II = I const)(
397  requires same_as<I const, II> AND indirectly_readable<II>)
398  constexpr iter_rvalue_reference_t<II> move() const //
399  noexcept(has_nothrow_iter_move_v<II>)
400  {
401  return iter_move(it_);
402  }
403 
404  public:
405  constexpr move_into_cursor() = default;
406  };
407  } // namespace detail
409 
411  {
412  template<typename I>
413  constexpr move_into_iterator<I> operator()(I it) const
414  {
415  return move_into_iterator<I>{std::move(it)};
416  }
417  };
418 
421 
422  namespace cpp20
423  {
424  using ranges::make_move_iterator;
425  using ranges::move_iterator;
426  using ranges::move_sentinel;
427  } // namespace cpp20
429 } // namespace ranges
430 
432 RANGES_DIAGNOSTIC_PUSH
433 RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
434 
435 namespace std
436 {
437  template<typename I>
438  struct iterator_traits<::ranges::move_iterator<I>>
439  {
440  using iterator_category = std::input_iterator_tag;
441  using difference_type = typename ::ranges::move_iterator<I>::difference_type;
442  using value_type = typename ::ranges::move_iterator<I>::value_type;
443  using reference = typename ::ranges::move_iterator<I>::reference;
444  using pointer = meta::_t<std::add_pointer<reference>>;
445  };
446 } // namespace std
447 
448 RANGES_DIAGNOSTIC_POP
450 
451 #include <range/v3/detail/epilogue.hpp>
452 
453 #endif // RANGES_V3_ITERATOR_MOVE_ITERATORS_HPP
#define CPP_broken_friend_member
INTERNAL ONLY.
Definition: concepts.hpp:447
CPP_concept indirectly_writable
\concept indirectly_writable
Definition: concepts.hpp:169
CPP_concept indirectly_readable
\concept indirectly_readable
Definition: concepts.hpp:147
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
typename T::type _t
Type alias for T::type.
Definition: meta.hpp:141
Definition: basic_iterator.hpp:532
Definition: move_iterators.hpp:205
Definition: move_iterators.hpp:277
Definition: move_iterators.hpp:411
Definition: move_iterators.hpp:33
Definition: move_iterators.hpp:218