1// Copyright (C) 2019 T. Zachary Laine
2//
3// Distributed under the Boost Software License, Version 1.0. (See
4// accompanying file LICENSE_1_0.txt or copy at
5// http://www.boost.org/LICENSE_1_0.txt)
6#ifndef BOOST_STL_INTERFACES_REVERSE_ITERATOR_HPP
7#define BOOST_STL_INTERFACES_REVERSE_ITERATOR_HPP
8
9#include <boost/stl_interfaces/iterator_interface.hpp>
10
11
12namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V1 {
13
14 namespace v1_dtl {
15 template<typename Iter>
16 constexpr auto ce_dist(Iter f, Iter l, std::random_access_iterator_tag)
17 -> decltype(l - f)
18 {
19 return l - f;
20 }
21 template<typename Iter, typename Tag>
22 constexpr auto ce_dist(Iter f, Iter l, Tag)
23 -> decltype(std::distance(f, l))
24 {
25 decltype(std::distance(f, l)) retval = 0;
26 for (; f != l; ++f) {
27 ++retval;
28 }
29 return retval;
30 }
31
32 template<typename Iter>
33 constexpr Iter ce_prev(Iter it)
34 {
35 return --it;
36 }
37
38 template<typename Iter, typename Offset>
39 constexpr void
40 ce_adv(Iter & f, Offset n, std::random_access_iterator_tag)
41 {
42 f += n;
43 }
44 template<typename Iter, typename Offset, typename Tag>
45 constexpr void ce_adv(Iter & f, Offset n, Tag)
46 {
47 if (0 < n) {
48 for (Offset i = 0; i < n; ++i) {
49 ++f;
50 }
51 } else {
52 for (Offset i = 0; i < -n; ++i) {
53 --f;
54 }
55 }
56 }
57 }
58
59 /** This type is very similar to the C++20 version of
60 `std::reverse_iterator`; it is `constexpr`-, `noexcept`-, and
61 proxy-friendly. */
62 template<typename BidiIter>
63 struct reverse_iterator
64 : iterator_interface<
65#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS
66 reverse_iterator<BidiIter>,
67#endif
68#if BOOST_STL_INTERFACES_USE_CONCEPTS
69 typename boost::stl_interfaces::v2::v2_dtl::iter_concept_t<
70 BidiIter>,
71#else
72 typename std::iterator_traits<BidiIter>::iterator_category,
73#endif
74 typename std::iterator_traits<BidiIter>::value_type,
75 typename std::iterator_traits<BidiIter>::reference,
76 typename std::iterator_traits<BidiIter>::pointer,
77 typename std::iterator_traits<BidiIter>::difference_type>
78 {
79 constexpr reverse_iterator() noexcept(noexcept(BidiIter())) : it_() {}
80 constexpr reverse_iterator(BidiIter it) noexcept(
81 noexcept(BidiIter(it))) :
82 it_(it)
83 {}
84 template<
85 typename BidiIter2,
86 typename E = std::enable_if_t<
87 std::is_convertible<BidiIter2, BidiIter>::value>>
88 reverse_iterator(reverse_iterator<BidiIter2> const & it) : it_(it.it_)
89 {}
90
91 friend BOOST_STL_INTERFACES_HIDDEN_FRIEND_CONSTEXPR auto
92 operator-(reverse_iterator lhs, reverse_iterator rhs) noexcept(
93 noexcept(v1_dtl::ce_dist(
94 lhs.it_,
95 rhs.it_,
96 typename std::iterator_traits<BidiIter>::iterator_category{})))
97 {
98 return -v1_dtl::ce_dist(
99 rhs.it_,
100 lhs.it_,
101 typename std::iterator_traits<BidiIter>::iterator_category{});
102 }
103
104 constexpr typename std::iterator_traits<BidiIter>::reference
105 operator*() const noexcept(
106 noexcept(std::prev(v1_dtl::ce_prev(std::declval<BidiIter &>()))))
107 {
108 return *v1_dtl::ce_prev(it_);
109 }
110
111 constexpr reverse_iterator & operator+=(
112 typename std::iterator_traits<BidiIter>::difference_type
113 n) noexcept(noexcept(v1_dtl::
114 ce_adv(
115 std::declval<BidiIter &>(),
116 -n,
117 typename std::iterator_traits<
118 BidiIter>::
119 iterator_category{})))
120 {
121 v1_dtl::ce_adv(
122 it_,
123 -n,
124 typename std::iterator_traits<BidiIter>::iterator_category{});
125 return *this;
126 }
127
128 constexpr BidiIter base() const noexcept { return it_; }
129
130 private:
131 friend access;
132 constexpr BidiIter & base_reference() noexcept { return it_; }
133 constexpr BidiIter const & base_reference() const noexcept
134 {
135 return it_;
136 }
137
138 template<typename BidiIter2>
139 friend struct reverse_iterator;
140
141 BidiIter it_;
142 };
143
144 template<typename BidiIter>
145 constexpr auto operator==(
146 reverse_iterator<BidiIter> lhs,
147 reverse_iterator<BidiIter>
148 rhs) noexcept(noexcept(lhs.base() == rhs.base()))
149 -> decltype(rhs.base() == lhs.base())
150 {
151 return lhs.base() == rhs.base();
152 }
153
154 template<typename BidiIter1, typename BidiIter2>
155 constexpr auto operator==(
156 reverse_iterator<BidiIter1> lhs,
157 reverse_iterator<BidiIter2>
158 rhs) noexcept(noexcept(lhs.base() == rhs.base()))
159 -> decltype(rhs.base() == lhs.base())
160 {
161 return lhs.base() == rhs.base();
162 }
163
164 /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
165 `BidiIter`. */
166 template<typename BidiIter>
167 auto make_reverse_iterator(BidiIter it)
168 {
169 return reverse_iterator<BidiIter>(it);
170 }
171
172}}}
173
174
175#if defined(BOOST_STL_INTERFACES_DOXYGEN) || BOOST_STL_INTERFACES_USE_CONCEPTS
176
177namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V2 {
178
179 /** A template alias for `std::reverse_iterator`. This only exists to
180 make migration from Boost.STLInterfaces to C++20 easier; switch to the
181 one in `std` as soon as you can. */
182 template<typename BidiIter>
183 using reverse_iterator = std::reverse_iterator<BidiIter>;
184
185
186 /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
187 `BidiIter`. This only exists to make migration from
188 Boost.STLInterfaces to C++20 easier; switch to the one in `std` as
189 soon as you can. */
190 template<typename BidiIter>
191 auto make_reverse_iterator(BidiIter it)
192 {
193 return reverse_iterator<BidiIter>(it);
194 }
195
196}}}
197
198namespace boost { namespace stl_interfaces { BOOST_STL_INTERFACES_NAMESPACE_V3 {
199
200 /** A template alias for `std::reverse_iterator`. This only exists to
201 make migration from Boost.STLInterfaces to C++20 easier; switch to the
202 one in `std` as soon as you can. */
203 template<typename BidiIter>
204 using reverse_iterator = std::reverse_iterator<BidiIter>;
205
206
207 /** Makes a `reverse_iterator<BidiIter>` from an iterator of type
208 `BidiIter`. This only exists to make migration from
209 Boost.STLInterfaces to C++20 easier; switch to the one in `std` as
210 soon as you can. */
211 template<typename BidiIter>
212 auto make_reverse_iterator(BidiIter it)
213 {
214 return reverse_iterator<BidiIter>(it);
215 }
216
217}}}
218
219#endif
220
221#endif
222

source code of boost/libs/stl_interfaces/include/boost/stl_interfaces/reverse_iterator.hpp