Horizon
Loading...
Searching...
No Matches
move_iterators.hpp
Go to the documentation of this file.
1
2// 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
20
24
25#include <range/v3/detail/prologue.hpp>
26
27namespace 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)(
103 {
104 return move_iterator(current_--);
105 }
106 CPP_member
107 auto operator+(difference_type n) const //
108 -> CPP_ret(move_iterator)(
110 {
111 return move_iterator(current_ + n);
112 }
113 CPP_member
114 auto operator+=(difference_type n)
115 -> CPP_ret(move_iterator &)(
117 {
118 current_ += n;
119 return *this;
120 }
121 CPP_member
122 auto operator-(difference_type n) const //
123 -> CPP_ret(move_iterator)(
125 {
126 return move_iterator(current_ - n);
127 }
128 CPP_member
129 auto operator-=(difference_type n) //
130 -> CPP_ret(move_iterator &)(
132 {
133 current_ -= n;
134 return *this;
135 }
136 CPP_member
137 auto operator[](difference_type n) const //
138 -> CPP_ret(reference)(
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>)(
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)(
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
420 RANGES_INLINE_VARIABLE(move_into_fn, move_into)
421
422 namespace cpp20
423 {
424 using ranges::make_move_iterator;
427 } // namespace cpp20
429} // namespace ranges
430
432RANGES_DIAGNOSTIC_PUSH
433RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
434
435namespace 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;
445 };
446} // namespace std
447
448RANGES_DIAGNOSTIC_POP
450
451#include <range/v3/detail/epilogue.hpp>
452
453#endif // RANGES_V3_ITERATOR_MOVE_ITERATORS_HPP
The bidirectional_iterator concept.
The forward_iterator concept.
The input_iterator concept.
The random_access_iterator concept.
The sentinel_for concept.
The sized_sentinel_for concept.
#define CPP_broken_friend_member
INTERNAL ONLY.
Definition concepts.hpp:447
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