Horizon
Loading...
Searching...
No Matches
basic_iterator.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Eric Niebler 2014-present
5// Copyright Casey Carter 2016
6//
7// Use, modification and distribution is subject to the
8// Boost Software License, Version 1.0. (See accompanying
9// file LICENSE_1_0.txt or copy at
10// http://www.boost.org/LICENSE_1_0.txt)
11//
12// Project home: https://github.com/ericniebler/range-v3
13//
14#ifndef RANGES_V3_ITERATOR_BASIC_ITERATOR_HPP
15#define RANGES_V3_ITERATOR_BASIC_ITERATOR_HPP
16
17#include <type_traits>
18#include <utility>
19
20#include <meta/meta.hpp>
21
22#include <concepts/concepts.hpp>
23
25
29#include <range/v3/utility/addressof.hpp>
33#include <range/v3/utility/static_const.hpp>
34
35#include <range/v3/detail/prologue.hpp>
36
37RANGES_DIAGNOSTIC_PUSH
38RANGES_DIAGNOSTIC_IGNORE_MULTIPLE_ASSIGNMENT_OPERATORS
39
40namespace ranges
41{
45 template<typename T>
46 struct basic_mixin : private box<T>
47 {
48 CPP_member
49 constexpr CPP_ctor(basic_mixin)()( //
50 noexcept(std::is_nothrow_default_constructible<T>::value) //
51 requires default_constructible<T>)
52 : box<T>{}
53 {}
54 CPP_member
55 constexpr explicit CPP_ctor(basic_mixin)(T && t)( //
56 noexcept(std::is_nothrow_move_constructible<T>::value) //
57 requires move_constructible<T>)
58 : box<T>(detail::move(t))
59 {}
60 CPP_member
61 constexpr explicit CPP_ctor(basic_mixin)(T const & t)( //
62 noexcept(std::is_nothrow_copy_constructible<T>::value) //
63 requires copy_constructible<T>)
64 : box<T>(t)
65 {}
66
67 protected:
68 using box<T>::get;
69 };
70
72 namespace detail
73 {
74 template<typename Cur>
75 using cursor_reference_t =
76 decltype(range_access::read(std::declval<Cur const &>()));
77
78 // Compute the rvalue reference type of a cursor
79 template<typename Cur>
80 auto cursor_move(Cur const & cur, int) -> decltype(range_access::move(cur));
81 template<typename Cur>
82 auto cursor_move(Cur const & cur, long) -> aux::move_t<cursor_reference_t<Cur>>;
83
84 template<typename Cur>
85 using cursor_rvalue_reference_t =
86 decltype(detail::cursor_move(std::declval<Cur const &>(), 42));
87
88 // Define conversion operators from the proxy reference type
89 // to the common reference types, so that basic_iterator can model readable
90 // even with getters/setters.
91 template<typename Derived, typename Head>
92 struct proxy_reference_conversion
93 {
94 operator Head() const
95 noexcept(noexcept(Head(Head(std::declval<Derived const &>().read_()))))
96 {
97 return Head(static_cast<Derived const *>(this)->read_());
98 }
99 };
100
101 // Collect the reference types associated with cursors
102 template<typename Cur, bool IsReadable>
103 struct cursor_traits_
104 {
105 private:
106 struct private_
107 {};
108
109 public:
110 using value_t_ = private_;
111 using reference_t_ = private_;
112 using rvalue_reference_t_ = private_;
113 using common_refs = meta::list<>;
114 };
115
116 template<typename Cur>
117 struct cursor_traits_<Cur, true>
118 {
119 using value_t_ = range_access::cursor_value_t<Cur>;
120 using reference_t_ = cursor_reference_t<Cur>;
121 using rvalue_reference_t_ = cursor_rvalue_reference_t<Cur>;
122
123 private:
124 using R1 = reference_t_;
125 using R2 = common_reference_t<reference_t_, value_t_ &>;
126 using R3 = common_reference_t<reference_t_, rvalue_reference_t_>;
127 using tmp1 = meta::list<value_t_, R1>;
128 using tmp2 =
130 using tmp3 =
132
133 public:
134 using common_refs = meta::unique<meta::pop_front<tmp3>>;
135 };
136
137 template<typename Cur>
138 using cursor_traits = cursor_traits_<Cur, (bool)readable_cursor<Cur>>;
139
140 template<typename Cur>
141 using cursor_value_t = typename cursor_traits<Cur>::value_t_;
142
143 template<typename Cur, bool IsReadable>
144 struct basic_proxy_reference_;
145 template<typename Cur>
146 using basic_proxy_reference =
147 basic_proxy_reference_<Cur, (bool)readable_cursor<Cur>>;
148
149 // The One Proxy Reference type to rule them all. basic_iterator uses this
150 // as the return type of operator* when the cursor type has a set() member
151 // function of the correct signature (i.e., if it can accept a value_type &&).
152 template<typename Cur, bool IsReadable /*= (bool) readable_cursor<Cur>*/>
153 struct RANGES_EMPTY_BASES basic_proxy_reference_
154 : cursor_traits<Cur>
155 // The following adds conversion operators to the common reference
156 // types, so that basic_proxy_reference can model readable
157 , meta::inherit<meta::transform<
158 typename cursor_traits<Cur>::common_refs,
159 meta::bind_front<meta::quote<proxy_reference_conversion>,
160 basic_proxy_reference_<Cur, IsReadable>>>>
161 {
162 private:
163 Cur * cur_;
164 template<typename, bool>
165 friend struct basic_proxy_reference_;
166 template<typename, typename>
167 friend struct proxy_reference_conversion;
168 using typename cursor_traits<Cur>::value_t_;
169 using typename cursor_traits<Cur>::reference_t_;
170 using typename cursor_traits<Cur>::rvalue_reference_t_;
171 static_assert((bool)common_reference_with<value_t_ &, reference_t_>,
172 "Your readable and writable cursor must have a value type and "
173 "a reference type that share a common reference type. See the "
174 "ranges::common_reference type trait.");
175 // BUGBUG make these private:
176 public:
177 constexpr reference_t_ read_() const noexcept(
178 noexcept(reference_t_(range_access::read(std::declval<Cur const &>()))))
179 {
180 return range_access::read(*cur_);
181 }
182 template<typename T>
183 constexpr void write_(T && t) const
184 {
185 range_access::write(*cur_, (T &&) t);
186 }
187 // public:
188 basic_proxy_reference_() = default;
189 basic_proxy_reference_(basic_proxy_reference_ const &) = default;
190 template(typename OtherCur)(
191 requires convertible_to<OtherCur *, Cur *>)
192 constexpr basic_proxy_reference_(
193 basic_proxy_reference<OtherCur> const & that) noexcept
194 : cur_(that.cur_)
195 {}
196 constexpr explicit basic_proxy_reference_(Cur & cur) noexcept
197 : cur_(&cur)
198 {}
199 CPP_member
200 constexpr auto operator=(basic_proxy_reference_ && that)
201 -> CPP_ret(basic_proxy_reference_ &)(
202 requires readable_cursor<Cur>)
203 {
204 return *this = that;
205 }
206 CPP_member
207 constexpr auto operator=(basic_proxy_reference_ const & that)
208 -> CPP_ret(basic_proxy_reference_ &)(
209 requires readable_cursor<Cur>)
210 {
211 this->write_(that.read_());
212 return *this;
213 }
214 CPP_member
215 constexpr auto operator=(basic_proxy_reference_ && that) const
216 -> CPP_ret(basic_proxy_reference_ const &)(
217 requires readable_cursor<Cur>)
218 {
219 return *this = that;
220 }
221 CPP_member
222 constexpr auto operator=(basic_proxy_reference_ const & that) const
223 -> CPP_ret(basic_proxy_reference_ const &)(
224 requires readable_cursor<Cur>)
225 {
226 this->write_(that.read_());
227 return *this;
228 }
229 template(typename OtherCur)(
230 requires readable_cursor<OtherCur> AND
231 writable_cursor<Cur, cursor_reference_t<OtherCur>>)
232 constexpr basic_proxy_reference_ & //
233 operator=(basic_proxy_reference<OtherCur> && that)
234 {
235 return *this = that;
236 }
237 template(typename OtherCur)(
238 requires readable_cursor<OtherCur> AND
239 writable_cursor<Cur, cursor_reference_t<OtherCur>>)
240 constexpr basic_proxy_reference_ & //
241 operator=(basic_proxy_reference<OtherCur> const & that)
242 {
243 this->write_(that.read_());
244 return *this;
245 }
246 template(typename OtherCur)(
247 requires readable_cursor<OtherCur> AND
248 writable_cursor<Cur, cursor_reference_t<OtherCur>>)
249 constexpr basic_proxy_reference_ const & //
250 operator=(basic_proxy_reference<OtherCur> && that) const
251 {
252 return *this = that;
253 }
254 template(typename OtherCur)(
255 requires readable_cursor<OtherCur> AND
256 writable_cursor<Cur, cursor_reference_t<OtherCur>>)
257 constexpr basic_proxy_reference_ const & //
258 operator=(basic_proxy_reference<OtherCur> const & that) const
259 {
260 this->write_(that.read_());
261 return *this;
262 }
263 template(typename T)(
264 requires writable_cursor<Cur, T>)
265 constexpr basic_proxy_reference_ & operator=(T && t) //
266 {
267 this->write_((T &&) t);
268 return *this;
269 }
270 template(typename T)(
271 requires writable_cursor<Cur, T>)
272 constexpr basic_proxy_reference_ const & operator=(T && t) const
273 {
274 this->write_((T &&) t);
275 return *this;
276 }
277 };
278
279 template(typename Cur, bool IsReadable)(
280 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
281 constexpr bool operator==(basic_proxy_reference_<Cur, IsReadable> const & x,
282 cursor_value_t<Cur> const & y)
283 {
284 return x.read_() == y;
285 }
286 template(typename Cur, bool IsReadable)(
287 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
288 constexpr bool operator!=(basic_proxy_reference_<Cur, IsReadable> const & x,
289 cursor_value_t<Cur> const & y)
290 {
291 return !(x == y);
292 }
293 template(typename Cur, bool IsReadable)(
294 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
295 constexpr bool operator==(cursor_value_t<Cur> const & x,
296 basic_proxy_reference_<Cur, IsReadable> const & y)
297 {
298 return x == y.read_();
299 }
300 template(typename Cur, bool IsReadable)(
301 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
302 constexpr bool operator!=(cursor_value_t<Cur> const & x,
303 basic_proxy_reference_<Cur, IsReadable> const & y)
304 {
305 return !(x == y);
306 }
307 template(typename Cur, bool IsReadable)(
308 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
309 constexpr bool operator==(basic_proxy_reference_<Cur, IsReadable> const & x,
310 basic_proxy_reference_<Cur, IsReadable> const & y)
311 {
312 return x.read_() == y.read_();
313 }
314 template(typename Cur, bool IsReadable)(
315 requires readable_cursor<Cur> AND equality_comparable<cursor_value_t<Cur>>)
316 constexpr bool operator!=(basic_proxy_reference_<Cur, IsReadable> const & x,
317 basic_proxy_reference_<Cur, IsReadable> const & y)
318 {
319 return !(x == y);
320 }
321
322 template<typename Cur>
323 using cpp20_iter_cat_of_t = //
324 std::enable_if_t< //
325 input_cursor<Cur>, //
327 contiguous_cursor<Cur>, //
330 random_access_cursor<Cur>, //
331 std::random_access_iterator_tag, //
333 bidirectional_cursor<Cur>, //
334 std::bidirectional_iterator_tag, //
336 forward_cursor<Cur>, //
337 std::forward_iterator_tag, //
338 std::input_iterator_tag>>>>>;
339
340 // clang-format off
343 template(typename C)(
344 concept (cpp17_input_cursor_)(C),
345 // Either it is not single-pass, or else we can create a
346 // proxy for postfix increment.
347 !range_access::single_pass_t<uncvref_t<C>>::value ||
348 (move_constructible<range_access::cursor_value_t<C>> &&
349 constructible_from<range_access::cursor_value_t<C>, cursor_reference_t<C>>)
350 );
351
354 template<typename C>
355 CPP_concept cpp17_input_cursor =
356 input_cursor<C> &&
357 sentinel_for_cursor<C, C> &&
358 CPP_concept_ref(cpp17_input_cursor_, C);
359
362 template(typename C)(
363 concept (cpp17_forward_cursor_)(C),
364 std::is_reference<cursor_reference_t<C>>::value
365 );
366
369 template<typename C>
370 CPP_concept cpp17_forward_cursor =
371 forward_cursor<C> &&
372 CPP_concept_ref(cpp17_forward_cursor_, C);
373 // clang-format on
374
375 template<typename Category, typename Base = void>
376 struct with_iterator_category : Base
377 {
378 using iterator_category = Category;
379 };
380
381 template<typename Category>
382 struct with_iterator_category<Category>
383 {
384 using iterator_category = Category;
385 };
386
387 template<typename Cur>
388 using cpp17_iter_cat_of_t = //
389 std::enable_if_t< //
390 cpp17_input_cursor<Cur>, //
392 random_access_cursor<Cur>, //
393 std::random_access_iterator_tag, //
395 bidirectional_cursor<Cur>, //
396 std::bidirectional_iterator_tag, //
398 cpp17_forward_cursor<Cur>, //
399 std::forward_iterator_tag, //
400 std::input_iterator_tag>>>>;
401
402 template<typename Cur, typename = void>
403 struct readable_iterator_associated_types_base : range_access::mixin_base_t<Cur>
404 {
405 readable_iterator_associated_types_base() = default;
406 using range_access::mixin_base_t<Cur>::mixin_base_t;
407 readable_iterator_associated_types_base(Cur && cur)
408 : range_access::mixin_base_t<Cur>(static_cast<Cur &&>(cur))
409 {}
410 readable_iterator_associated_types_base(Cur const & cur)
411 : range_access::mixin_base_t<Cur>(cur)
412 {}
413 };
414
415 template<typename Cur>
416 struct readable_iterator_associated_types_base<
417 Cur, always_<void, cpp17_iter_cat_of_t<Cur>>>
418 : range_access::mixin_base_t<Cur>
419 {
420 using iterator_category = cpp17_iter_cat_of_t<Cur>;
421 readable_iterator_associated_types_base() = default;
422 using range_access::mixin_base_t<Cur>::mixin_base_t;
423 readable_iterator_associated_types_base(Cur && cur)
424 : range_access::mixin_base_t<Cur>(static_cast<Cur &&>(cur))
425 {}
426 readable_iterator_associated_types_base(Cur const & cur)
427 : range_access::mixin_base_t<Cur>(cur)
428 {}
429 };
430
431 template<typename Cur, bool IsReadable /*= (bool) readable_cursor<Cur>*/>
432 struct iterator_associated_types_base_ : range_access::mixin_base_t<Cur>
433 {
434 // BUGBUG
435 // protected:
436 using iter_reference_t = basic_proxy_reference<Cur>;
437 using const_reference_t = basic_proxy_reference<Cur const>;
438
439 public:
440 using reference = void;
441 using difference_type = range_access::cursor_difference_t<Cur>;
442
443 iterator_associated_types_base_() = default;
444 using range_access::mixin_base_t<Cur>::mixin_base_t;
445 iterator_associated_types_base_(Cur && cur)
446 : range_access::mixin_base_t<Cur>(static_cast<Cur &&>(cur))
447 {}
448 iterator_associated_types_base_(Cur const & cur)
449 : range_access::mixin_base_t<Cur>(cur)
450 {}
451 };
452
453 template<typename Cur>
454 using cursor_arrow_t = decltype(range_access::arrow(std::declval<Cur const &>()));
455
456 template<typename Cur>
457 struct iterator_associated_types_base_<Cur, true>
458 : readable_iterator_associated_types_base<Cur>
459 {
460 // BUGBUG
461 // protected:
462 using iter_reference_t =
464 basic_proxy_reference<Cur const>,
466 basic_proxy_reference<Cur>, cursor_reference_t<Cur>>>;
467 using const_reference_t =
469 basic_proxy_reference<Cur const>, cursor_reference_t<Cur>>;
470
471 public:
472 using difference_type = range_access::cursor_difference_t<Cur>;
473 using value_type = range_access::cursor_value_t<Cur>;
474 using reference = iter_reference_t;
475 using iterator_concept = cpp20_iter_cat_of_t<Cur>;
476 using pointer = meta::_t<
478 (bool)has_cursor_arrow<Cur>,
480 std::add_pointer<reference>>>;
481 using common_reference = common_reference_t<reference, value_type &>;
482
483 iterator_associated_types_base_() = default;
484 using readable_iterator_associated_types_base<
485 Cur>::readable_iterator_associated_types_base;
486 iterator_associated_types_base_(Cur && cur)
487 : readable_iterator_associated_types_base<Cur>(static_cast<Cur &&>(cur))
488 {}
489 iterator_associated_types_base_(Cur const & cur)
490 : readable_iterator_associated_types_base<Cur>(cur)
491 {}
492 };
493
494 template<typename Cur>
495 using iterator_associated_types_base =
496 iterator_associated_types_base_<Cur, (bool)readable_cursor<Cur>>;
497
498 template<typename Value>
499 struct postfix_increment_proxy
500 {
501 private:
502 Value cache_;
503
504 public:
505 template<typename T>
506 constexpr postfix_increment_proxy(T && t)
507 : cache_(static_cast<T &&>(t))
508 {}
509 constexpr Value const & operator*() const noexcept
510 {
511 return cache_;
512 }
513 };
514 } // namespace detail
516
517#if RANGES_BROKEN_CPO_LOOKUP
518 namespace _basic_iterator_
519 {
520 template<typename>
521 struct adl_hook
522 {};
523 } // namespace _basic_iterator_
524#endif
525
526 template<typename Cur>
527 struct RANGES_EMPTY_BASES basic_iterator
528 : detail::iterator_associated_types_base<Cur>
529#if RANGES_BROKEN_CPO_LOOKUP
530 , private _basic_iterator_::adl_hook<basic_iterator<Cur>>
531#endif
532 {
533 private:
534 template<typename>
535 friend struct basic_iterator;
536 friend range_access;
537 using base_t = detail::iterator_associated_types_base<Cur>;
538 using mixin_t = range_access::mixin_base_t<Cur>;
539 static_assert((bool)detail::cursor<Cur>, "");
540 using assoc_types_ = detail::iterator_associated_types_base<Cur>;
541 using typename assoc_types_::const_reference_t;
542 using typename assoc_types_::iter_reference_t;
543 constexpr Cur & pos() noexcept
544 {
545 return this->mixin_t::basic_mixin::get();
546 }
547 constexpr Cur const & pos() const noexcept
548 {
549 return this->mixin_t::basic_mixin::get();
550 }
551
552 public:
553 using typename assoc_types_::difference_type;
554 constexpr basic_iterator() = default;
555 template(typename OtherCur)(
556 requires (!same_as<OtherCur, Cur>) AND convertible_to<OtherCur, Cur> AND
557 constructible_from<mixin_t, OtherCur>)
559 : base_t{std::move(that.pos())}
560 {}
561 // Mix in any additional constructors provided by the mixin
562 using base_t::base_t;
563
564 explicit basic_iterator(Cur && cur)
565 : base_t(static_cast<Cur &&>(cur))
566 {}
567
568 explicit basic_iterator(Cur const & cur)
569 : base_t(cur)
570 {}
571
572 template(typename OtherCur)(
573 requires (!same_as<OtherCur, Cur>) AND convertible_to<OtherCur, Cur>)
574 constexpr basic_iterator & operator=(basic_iterator<OtherCur> that)
575 {
576 pos() = std::move(that.pos());
577 return *this;
578 }
579
580 CPP_member
581 constexpr auto operator*() const
582 noexcept(noexcept(range_access::read(std::declval<Cur const &>())))
583 -> CPP_ret(const_reference_t)(
584 requires detail::readable_cursor<Cur> &&
585 (!detail::is_writable_cursor_v<Cur>))
586 {
587 return range_access::read(pos());
588 }
589 CPP_member
590 constexpr auto operator*() //
591 noexcept(noexcept(iter_reference_t{std::declval<Cur &>()})) //
592 -> CPP_ret(iter_reference_t)(
593 requires detail::has_cursor_next<Cur> &&
594 detail::is_writable_cursor_v<Cur>)
595 {
596 return iter_reference_t{pos()};
597 }
598 CPP_member
599 constexpr auto operator*() const
600 noexcept(noexcept(const_reference_t{std::declval<Cur const &>()}))
601 -> CPP_ret(const_reference_t)(
602 requires detail::has_cursor_next<Cur> &&
603 detail::is_writable_cursor_v<Cur const>)
604 {
605 return const_reference_t{pos()};
606 }
607 CPP_member
608 constexpr auto operator*() noexcept //
609 -> CPP_ret(basic_iterator &)(
610 requires (!detail::has_cursor_next<Cur>))
611 {
612 return *this;
613 }
614
615 // Use cursor's arrow() member, if any.
616 template(typename C = Cur)(
617 requires detail::has_cursor_arrow<C>)
618 constexpr detail::cursor_arrow_t<C> operator-> () const
619 noexcept(noexcept(range_access::arrow(std::declval<C const &>())))
620 {
621 return range_access::arrow(pos());
622 }
623 // Otherwise, if iter_reference_t is an lvalue reference to cv-qualified
624 // iter_value_t, return the address of **this.
625 template(typename C = Cur)(
626 requires (!detail::has_cursor_arrow<C>) AND detail::readable_cursor<C> AND
627 std::is_lvalue_reference<const_reference_t>::value AND
628 same_as<typename detail::iterator_associated_types_base<C>::value_type,
629 uncvref_t<const_reference_t>>)
630 constexpr std::add_pointer_t<const_reference_t> operator-> () const
631 noexcept(noexcept(*std::declval<basic_iterator const &>()))
632 {
633 return detail::addressof(**this);
634 }
635
636 CPP_member
637 constexpr auto operator++() //
638 -> CPP_ret(basic_iterator &)(
639 requires detail::has_cursor_next<Cur>)
640 {
641 range_access::next(pos());
642 return *this;
643 }
644 CPP_member
645 constexpr auto operator++() noexcept //
646 -> CPP_ret(basic_iterator &)(
647 requires (!detail::has_cursor_next<Cur>))
648 {
649 return *this;
650 }
651
652 private:
653 constexpr basic_iterator post_increment_(std::false_type, int)
654 {
655 basic_iterator tmp{*this};
656 ++*this;
657 return tmp;
658 }
659 // Attempt to satisfy the C++17 iterator requirements by returning a
660 // proxy from postfix increment:
661 template(typename A = assoc_types_, typename V = typename A::value_type)(
662 requires constructible_from<V, typename A::reference> AND
663 move_constructible<V>)
664 constexpr auto post_increment_(std::true_type, int) //
665 -> detail::postfix_increment_proxy<V>
666 {
667 detail::postfix_increment_proxy<V> p{**this};
668 ++*this;
669 return p;
670 }
671 constexpr void post_increment_(std::true_type, long)
672 {
673 ++*this;
674 }
675
676 public:
677 CPP_member
678 constexpr auto operator++(int)
679 {
680 return this->post_increment_(meta::bool_ < detail::input_cursor<Cur> &&
681 !detail::forward_cursor<Cur>> {},
682 0);
683 }
684
685 CPP_member
686 constexpr auto operator--()
687 -> CPP_ret(basic_iterator &)(
688 requires detail::bidirectional_cursor<Cur>)
689 {
690 range_access::prev(pos());
691 return *this;
692 }
693 CPP_member
694 constexpr auto operator--(int) //
695 -> CPP_ret(basic_iterator)(
696 requires detail::bidirectional_cursor<Cur>)
697 {
698 basic_iterator tmp(*this);
699 --*this;
700 return tmp;
701 }
702 CPP_member
703 constexpr auto operator+=(difference_type n) //
704 -> CPP_ret(basic_iterator &)(
705 requires detail::random_access_cursor<Cur>)
706 {
707 range_access::advance(pos(), n);
708 return *this;
709 }
710 CPP_member
711 constexpr auto operator-=(difference_type n) //
712 -> CPP_ret(basic_iterator &)(
713 requires detail::random_access_cursor<Cur>)
714 {
715 range_access::advance(pos(), (difference_type)-n);
716 return *this;
717 }
718 CPP_member
719 constexpr auto operator[](difference_type n) const //
720 -> CPP_ret(const_reference_t)(
721 requires detail::random_access_cursor<Cur>)
722 {
723 return *(*this + n);
724 }
725
726#if !RANGES_BROKEN_CPO_LOOKUP
727 // Optionally support hooking iter_move when the cursor sports a
728 // move() member function.
729 template<typename C = Cur>
730 friend constexpr auto iter_move(basic_iterator const & it) noexcept(
731 noexcept(range_access::move(std::declval<C const &>())))
732 -> CPP_broken_friend_ret(
733 decltype(range_access::move(std::declval<C const &>())))(
734 requires same_as<C, Cur> && detail::input_cursor<Cur>)
735 {
736 return range_access::move(it.pos());
737 }
738#endif
739 };
740
741 template(typename Cur, typename Cur2)(
742 requires detail::sentinel_for_cursor<Cur2, Cur>)
743 constexpr bool operator==(basic_iterator<Cur> const & left,
744 basic_iterator<Cur2> const & right)
745 {
746 return range_access::equal(range_access::pos(left), range_access::pos(right));
747 }
748 template(typename Cur, typename Cur2)(
749 requires detail::sentinel_for_cursor<Cur2, Cur>)
750 constexpr bool operator!=(basic_iterator<Cur> const & left,
751 basic_iterator<Cur2> const & right)
752 {
753 return !(left == right);
754 }
755 template(typename Cur, typename S)(
756 requires detail::sentinel_for_cursor<S, Cur>)
757 constexpr bool operator==(basic_iterator<Cur> const & left,
758 S const & right)
759 {
760 return range_access::equal(range_access::pos(left), right);
761 }
762 template(typename Cur, typename S)(
763 requires detail::sentinel_for_cursor<S, Cur>)
764 constexpr bool operator!=(basic_iterator<Cur> const & left,
765 S const & right)
766 {
767 return !(left == right);
768 }
769 template(typename S, typename Cur)(
770 requires detail::sentinel_for_cursor<S, Cur>)
771 constexpr bool operator==(S const & left,
772 basic_iterator<Cur> const & right)
773 {
774 return right == left;
775 }
776 template(typename S, typename Cur)(
777 requires detail::sentinel_for_cursor<S, Cur>)
778 constexpr bool operator!=(S const & left,
779 basic_iterator<Cur> const & right)
780 {
781 return right != left;
782 }
783
784 template(typename Cur)(
785 requires detail::random_access_cursor<Cur>)
786 constexpr basic_iterator<Cur> //
787 operator+(basic_iterator<Cur> left, typename basic_iterator<Cur>::difference_type n)
788 {
789 left += n;
790 return left;
791 }
792 template(typename Cur)(
793 requires detail::random_access_cursor<Cur>)
794 constexpr basic_iterator<Cur> //
795 operator+(typename basic_iterator<Cur>::difference_type n, basic_iterator<Cur> right)
796 {
797 right += n;
798 return right;
799 }
800 template(typename Cur)(
801 requires detail::random_access_cursor<Cur>)
802 constexpr basic_iterator<Cur> //
803 operator-(basic_iterator<Cur> left, typename basic_iterator<Cur>::difference_type n)
804 {
805 left -= n;
806 return left;
807 }
808 template(typename Cur2, typename Cur)(
809 requires detail::sized_sentinel_for_cursor<Cur2, Cur>)
810 constexpr typename basic_iterator<Cur>::difference_type //
811 operator-(basic_iterator<Cur2> const & left, basic_iterator<Cur> const & right)
812 {
813 return range_access::distance_to(range_access::pos(right),
814 range_access::pos(left));
815 }
816 template(typename S, typename Cur)(
817 requires detail::sized_sentinel_for_cursor<S, Cur>)
818 constexpr typename basic_iterator<Cur>::difference_type //
819 operator-(S const & left, basic_iterator<Cur> const & right)
820 {
821 return range_access::distance_to(range_access::pos(right), left);
822 }
823 template(typename Cur, typename S)(
824 requires detail::sized_sentinel_for_cursor<S, Cur>)
825 constexpr typename basic_iterator<Cur>::difference_type //
826 operator-(basic_iterator<Cur> const & left, S const & right)
827 {
828 return -(right - left);
829 }
830 // Asymmetric comparisons
831 template(typename Left, typename Right)(
832 requires detail::sized_sentinel_for_cursor<Right, Left>)
833 constexpr bool operator<(basic_iterator<Left> const & left,
834 basic_iterator<Right> const & right)
835 {
836 return 0 < (right - left);
837 }
838 template(typename Left, typename Right)(
839 requires detail::sized_sentinel_for_cursor<Right, Left>)
840 constexpr bool operator<=(basic_iterator<Left> const & left,
841 basic_iterator<Right> const & right)
842 {
843 return 0 <= (right - left);
844 }
845 template(typename Left, typename Right)(
846 requires detail::sized_sentinel_for_cursor<Right, Left>)
847 constexpr bool operator>(basic_iterator<Left> const & left,
848 basic_iterator<Right> const & right)
849 {
850 return (right - left) < 0;
851 }
852 template(typename Left, typename Right)(
853 requires detail::sized_sentinel_for_cursor<Right, Left>)
854 constexpr bool operator>=(basic_iterator<Left> const & left,
855 basic_iterator<Right> const & right)
856 {
857 return (right - left) <= 0;
858 }
859
860#if RANGES_BROKEN_CPO_LOOKUP
861 namespace _basic_iterator_
862 {
863 // Optionally support hooking iter_move when the cursor sports a
864 // move() member function.
865 template<typename Cur>
866 constexpr auto iter_move(basic_iterator<Cur> const & it) noexcept(
867 noexcept(range_access::move(std::declval<Cur const &>())))
868 -> CPP_broken_friend_ret(
869 decltype(range_access::move(std::declval<Cur const &>())))(
870 requires detail::input_cursor<Cur>)
871 {
872 return range_access::move(range_access::pos(it));
873 }
874 } // namespace _basic_iterator_
875#endif
876
878 struct get_cursor_fn
879 {
880 template<typename Cur>
881 constexpr Cur & operator()(basic_iterator<Cur> & it) const noexcept
882 {
883 return range_access::pos(it);
884 }
885 template<typename Cur>
886 constexpr Cur const & operator()(basic_iterator<Cur> const & it) const noexcept
887 {
888 return range_access::pos(it);
889 }
890 template<typename Cur>
891 constexpr Cur operator()(basic_iterator<Cur> && it) const
892 noexcept(std::is_nothrow_move_constructible<Cur>::value)
893 {
894 return range_access::pos(std::move(it));
895 }
896 };
897
899 RANGES_INLINE_VARIABLE(get_cursor_fn, get_cursor)
901} // namespace ranges
902
904namespace concepts
905{
906 // common_reference specializations for basic_proxy_reference
907 template<typename Cur, typename U, template<typename> class TQual,
908 template<typename> class UQual>
909 struct basic_common_reference<::ranges::detail::basic_proxy_reference_<Cur, true>, U,
910 TQual, UQual>
911 : basic_common_reference<::ranges::detail::cursor_reference_t<Cur>, U, TQual, UQual>
912 {};
913 template<typename T, typename Cur, template<typename> class TQual,
914 template<typename> class UQual>
915 struct basic_common_reference<T, ::ranges::detail::basic_proxy_reference_<Cur, true>,
916 TQual, UQual>
917 : basic_common_reference<T, ::ranges::detail::cursor_reference_t<Cur>, TQual, UQual>
918 {};
919 template<typename Cur1, typename Cur2, template<typename> class TQual,
920 template<typename> class UQual>
921 struct basic_common_reference<::ranges::detail::basic_proxy_reference_<Cur1, true>,
922 ::ranges::detail::basic_proxy_reference_<Cur2, true>,
923 TQual, UQual>
924 : basic_common_reference<::ranges::detail::cursor_reference_t<Cur1>,
925 ::ranges::detail::cursor_reference_t<Cur2>, TQual, UQual>
926 {};
927
928 // common_type specializations for basic_proxy_reference
929 template<typename Cur, typename U>
930 struct common_type<::ranges::detail::basic_proxy_reference_<Cur, true>, U>
931 : common_type<::ranges::range_access::cursor_value_t<Cur>, U>
932 {};
933 template<typename T, typename Cur>
934 struct common_type<T, ::ranges::detail::basic_proxy_reference_<Cur, true>>
935 : common_type<T, ::ranges::range_access::cursor_value_t<Cur>>
936 {};
937 template<typename Cur1, typename Cur2>
938 struct common_type<::ranges::detail::basic_proxy_reference_<Cur1, true>,
939 ::ranges::detail::basic_proxy_reference_<Cur2, true>>
940 : common_type<::ranges::range_access::cursor_value_t<Cur1>,
941 ::ranges::range_access::cursor_value_t<Cur2>>
942 {};
943} // namespace concepts
944
945#if RANGES_CXX_VER > RANGES_CXX_STD_17
946RANGES_DIAGNOSTIC_PUSH
947RANGES_DIAGNOSTIC_IGNORE_MISMATCHED_TAGS
948RANGES_BEGIN_NAMESPACE_STD
949RANGES_BEGIN_NAMESPACE_VERSION
950 template<typename, typename, template <typename> class, template<typename> class>
951 struct basic_common_reference;
952
953 // common_reference specializations for basic_proxy_reference
954 template<typename Cur, typename U, template<typename> class TQual,
955 template<typename> class UQual>
956 struct basic_common_reference<::ranges::detail::basic_proxy_reference_<Cur, true>, U,
957 TQual, UQual>
958 : basic_common_reference<::ranges::detail::cursor_reference_t<Cur>, U, TQual, UQual>
959 {};
960 template<typename T, typename Cur, template<typename> class TQual,
961 template<typename> class UQual>
962 struct basic_common_reference<T, ::ranges::detail::basic_proxy_reference_<Cur, true>,
963 TQual, UQual>
964 : basic_common_reference<T, ::ranges::detail::cursor_reference_t<Cur>, TQual, UQual>
965 {};
966 template<typename Cur1, typename Cur2, template<typename> class TQual,
967 template<typename> class UQual>
968 struct basic_common_reference<::ranges::detail::basic_proxy_reference_<Cur1, true>,
969 ::ranges::detail::basic_proxy_reference_<Cur2, true>,
970 TQual, UQual>
971 : basic_common_reference<::ranges::detail::cursor_reference_t<Cur1>,
972 ::ranges::detail::cursor_reference_t<Cur2>, TQual, UQual>
973 {};
974
975 template<typename...>
976 struct common_type;
977
978 // common_type specializations for basic_proxy_reference
979 template<typename Cur, typename U>
980 struct common_type<::ranges::detail::basic_proxy_reference_<Cur, true>, U>
981 : common_type<::ranges::range_access::cursor_value_t<Cur>, U>
982 {};
983 template<typename T, typename Cur>
984 struct common_type<T, ::ranges::detail::basic_proxy_reference_<Cur, true>>
985 : common_type<T, ::ranges::range_access::cursor_value_t<Cur>>
986 {};
987 template<typename Cur1, typename Cur2>
988 struct common_type<::ranges::detail::basic_proxy_reference_<Cur1, true>,
989 ::ranges::detail::basic_proxy_reference_<Cur2, true>>
990 : common_type<::ranges::range_access::cursor_value_t<Cur1>,
991 ::ranges::range_access::cursor_value_t<Cur2>>
992 {};
993RANGES_END_NAMESPACE_VERSION
994RANGES_END_NAMESPACE_STD
995RANGES_DIAGNOSTIC_POP
996#endif // RANGES_CXX_VER > RANGES_CXX_STD_17
997
998namespace ranges
999{
1001 namespace detail
1002 {
1003 template<typename Cur, bool IsReadable>
1004 struct std_iterator_traits_
1005 {
1006 using difference_type =
1007 typename iterator_associated_types_base<Cur>::difference_type;
1008 using value_type = void;
1009 using reference = void;
1010 using pointer = void;
1011 using iterator_category = std::output_iterator_tag;
1012 using iterator_concept = std::output_iterator_tag;
1013 };
1014
1015 template<typename Cur>
1016 struct std_iterator_traits_<Cur, true> : iterator_associated_types_base<Cur>
1017 {};
1018
1019 template<typename Cur>
1020 using std_iterator_traits = std_iterator_traits_<Cur, (bool)readable_cursor<Cur>>;
1021 } // namespace detail
1023} // namespace ranges
1024
1025namespace std
1026{
1027 template<typename Cur>
1028 struct iterator_traits<::ranges::basic_iterator<Cur>>
1029 : ::ranges::detail::std_iterator_traits<Cur>
1030 {};
1031} // namespace std
1033
1034RANGES_DIAGNOSTIC_POP
1035
1036#include <range/v3/detail/epilogue.hpp>
1037
1038#endif
Definition box.hpp:163
meta::_t< detail::inherit_< L > > inherit
A type that inherits from all the types in the list.
Definition meta.hpp:3114
meta::if_c< std::is_reference< R >::value, meta::_t< std::remove_reference< R > > &&, detail::decay_t< R > > move_t
Definition move.hpp:59
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
_t< detail::_if_< list< Args... > > > if_
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1247
typename detail::_cond< If >::template invoke< Then, Else > conditional_t
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1148
fold< L, list<>, quote_trait< detail::insert_back_ > > unique
Return a new meta::list where all duplicate elements have been removed.
Definition meta.hpp:3157
apply< bind_back< quote< list >, Ts... >, L > push_back
Return a new meta::list by adding the element T to the back of L.
Definition meta.hpp:2173
Tiny meta-programming library.
Point operator*(double s, const Point &a)
Multiply point by scalar.
Definition shapes.h:250
Point operator-(const Point &a, const Point &b)
Subtract two points_ component-wise.
Definition shapes.h:244
A wrapper that defers the instantiation of a template C with type parameters Ts in a lambda or let ex...
Definition meta.hpp:787
A list of types.
Definition meta.hpp:1684
Definition basic_iterator.hpp:532
Definition basic_iterator.hpp:47
Definition traits.hpp:48