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