1 /// \file 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_REVERSE_ITERATOR_HPP 14 #define RANGES_V3_ITERATOR_REVERSE_ITERATOR_HPP 15 16 #include <utility> 17 18 #include <range/v3/range_fwd.hpp> 19 20 #include <range/v3/iterator/basic_iterator.hpp> 21 #include <range/v3/iterator/concepts.hpp> 22 23 #include <range/v3/detail/prologue.hpp> 24 25 namespace ranges 26 { 27 /// \addtogroup group-iterator 28 /// @{ 29 30 /// \cond 31 namespace detail 32 { 33 template<typename I> 34 struct reverse_cursor 35 { 36 private: 37 CPP_assert(bidirectional_iterator<I>); 38 friend range_access; 39 template<typename OtherI> 40 friend struct reverse_cursor; 41 struct mixin : basic_mixin<reverse_cursor> 42 { 43 mixin() = default; 44 #ifndef _MSC_VER 45 using basic_mixin<reverse_cursor>::basic_mixin; 46 #else mixinranges::detail::reverse_cursor::mixin47 constexpr explicit mixin(reverse_cursor && cur) 48 : basic_mixin<reverse_cursor>(static_cast<reverse_cursor &&>(cur)) 49 {} mixinranges::detail::reverse_cursor::mixin50 constexpr explicit mixin(reverse_cursor const & cur) 51 : basic_mixin<reverse_cursor>(cur) 52 {} 53 #endif mixinranges::detail::reverse_cursor::mixin54 constexpr mixin(I it) 55 : mixin{reverse_cursor{it}} 56 {} baseranges::detail::reverse_cursor::mixin57 constexpr I base() const 58 { 59 return this->get().base(); 60 } 61 }; 62 63 I it_; 64 reverse_cursorranges::detail::reverse_cursor65 constexpr reverse_cursor(I it) 66 : it_(std::move(it)) 67 {} readranges::detail::reverse_cursor68 constexpr iter_reference_t<I> read() const 69 { 70 return *arrow(); 71 } arrowranges::detail::reverse_cursor72 constexpr I arrow() const 73 { 74 auto tmp = it_; 75 --tmp; 76 return tmp; 77 } baseranges::detail::reverse_cursor78 constexpr I base() const 79 { 80 return it_; 81 } 82 template(typename J)( 83 /// \pre 84 requires sentinel_for<J, I>) 85 constexpr bool equal(reverse_cursor<J> const & that) const 86 { 87 return it_ == that.it_; 88 } 89 constexpr void next() 90 { 91 --it_; 92 } 93 constexpr void prev() 94 { 95 ++it_; 96 } 97 CPP_member 98 constexpr auto advance(iter_difference_t<I> n) // 99 -> CPP_ret(void)( 100 /// \pre 101 requires random_access_iterator<I>) 102 { 103 it_ -= n; 104 } 105 template(typename J)( 106 /// \pre 107 requires sized_sentinel_for<J, I>) 108 constexpr iter_difference_t<I> distance_to(reverse_cursor<J> const & that) // 109 const 110 { 111 return it_ - that.base(); 112 } moveranges::detail::reverse_cursor113 constexpr iter_rvalue_reference_t<I> move() const 114 noexcept(noexcept((void)I(I(it_)), (void)--const_cast<I &>(it_), 115 iter_move(it_))) 116 { 117 auto tmp = it_; 118 --tmp; 119 return iter_move(tmp); 120 } 121 122 public: 123 reverse_cursor() = default; 124 template(typename U)( 125 /// \pre 126 requires convertible_to<U, I>) 127 constexpr reverse_cursor(reverse_cursor<U> const & u) 128 : it_(u.base()) 129 {} 130 }; 131 } // namespace detail 132 /// \endcond 133 134 struct make_reverse_iterator_fn 135 { 136 template(typename I)( 137 /// \pre 138 requires bidirectional_iterator<I>) 139 constexpr reverse_iterator<I> operator()(I i) const 140 { 141 return reverse_iterator<I>(i); 142 } 143 }; 144 145 RANGES_INLINE_VARIABLE(make_reverse_iterator_fn, make_reverse_iterator) 146 147 namespace cpp20 148 { 149 using ranges::make_reverse_iterator; 150 using ranges::reverse_iterator; 151 } // namespace cpp20 152 /// @} 153 } // namespace ranges 154 155 #include <range/v3/detail/epilogue.hpp> 156 157 #endif // RANGES_V3_ITERATOR_REVERSE_ITERATOR_HPP 158