1 | #pragma once |
2 | |
3 | /** |
4 | * A constexpr std::reverse_iterator for C++11. |
5 | * Implementation taken from libstdc++, |
6 | * https://raw.githubusercontent.com/gcc-mirror/gcc/gcc-9_2_0-release/libstdc%2B%2B-v3/include/bits/stl_iterator.h |
7 | * adapted to our code base and constexpr'ified. |
8 | */ |
9 | |
10 | // Copyright (C) 2001-2019 Free Software Foundation, Inc. |
11 | // |
12 | // This file is part of the GNU ISO C++ Library. This library is free |
13 | // software; you can redistribute it and/or modify it under the |
14 | // terms of the GNU General Public License as published by the |
15 | // Free Software Foundation; either version 3, or (at your option) |
16 | // any later version. |
17 | |
18 | // This library is distributed in the hope that it will be useful, |
19 | // but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | // GNU General Public License for more details. |
22 | |
23 | // Under Section 7 of GPL version 3, you are granted additional |
24 | // permissions described in the GCC Runtime Library Exception, version |
25 | // 3.1, as published by the Free Software Foundation. |
26 | |
27 | // You should have received a copy of the GNU General Public License and |
28 | // a copy of the GCC Runtime Library Exception along with this program; |
29 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
30 | // <http://www.gnu.org/licenses/>. |
31 | |
32 | /* |
33 | * |
34 | * Copyright (c) 1994 |
35 | * Hewlett-Packard Company |
36 | * |
37 | * Permission to use, copy, modify, distribute and sell this software |
38 | * and its documentation for any purpose is hereby granted without fee, |
39 | * provided that the above copyright notice appear in all copies and |
40 | * that both that copyright notice and this permission notice appear |
41 | * in supporting documentation. Hewlett-Packard Company makes no |
42 | * representations about the suitability of this software for any |
43 | * purpose. It is provided "as is" without express or implied warranty. |
44 | * |
45 | * |
46 | * Copyright (c) 1996-1998 |
47 | * Silicon Graphics Computer Systems, Inc. |
48 | * |
49 | * Permission to use, copy, modify, distribute and sell this software |
50 | * and its documentation for any purpose is hereby granted without fee, |
51 | * provided that the above copyright notice appear in all copies and |
52 | * that both that copyright notice and this permission notice appear |
53 | * in supporting documentation. Silicon Graphics makes no |
54 | * representations about the suitability of this software for any |
55 | * purpose. It is provided "as is" without express or implied warranty. |
56 | */ |
57 | |
58 | #include <c10/util/C++17.h> |
59 | #include <iterator> |
60 | |
61 | namespace c10 { |
62 | |
63 | template <typename _Iterator> |
64 | class reverse_iterator { |
65 | protected: |
66 | _Iterator current; |
67 | |
68 | using __traits_type = std::iterator_traits<_Iterator>; |
69 | |
70 | public: |
71 | using iterator_type = _Iterator; |
72 | using value_type = typename __traits_type::value_type; |
73 | using difference_type = typename __traits_type::difference_type; |
74 | using pointer = typename __traits_type::pointer; |
75 | using reference = typename __traits_type::reference; |
76 | using iterator_category = typename __traits_type::iterator_category; |
77 | |
78 | constexpr reverse_iterator() : current() {} |
79 | |
80 | explicit constexpr reverse_iterator(iterator_type __x) : current(__x) {} |
81 | |
82 | constexpr reverse_iterator(const reverse_iterator& __x) |
83 | : current(__x.current) {} |
84 | |
85 | constexpr reverse_iterator& operator=(const reverse_iterator& rhs) noexcept { |
86 | current = rhs.current; |
87 | return current; |
88 | } |
89 | |
90 | template <typename _Iter> |
91 | constexpr reverse_iterator(const reverse_iterator<_Iter>& __x) |
92 | : current(__x.base()) {} |
93 | |
94 | constexpr iterator_type base() const { |
95 | return current; |
96 | } |
97 | |
98 | constexpr reference operator*() const { |
99 | #if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 |
100 | _Iterator iter = current; |
101 | return *--iter; |
102 | #else |
103 | // Only works for random access iterators if we're not C++14 :( |
104 | return *(current - 1); |
105 | #endif |
106 | } |
107 | |
108 | constexpr pointer operator->() const { |
109 | #if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 |
110 | _Iterator iter = current; |
111 | return _S_to_pointer(--iter); |
112 | #else |
113 | // Only works for random access iterators if we're not C++14 :( |
114 | return _S_to_pointer(current - 1); |
115 | #endif |
116 | } |
117 | |
118 | constexpr reverse_iterator& operator++() { |
119 | --current; |
120 | return *this; |
121 | } |
122 | |
123 | constexpr reverse_iterator operator++(int) { |
124 | reverse_iterator __tmp = *this; |
125 | --current; |
126 | return __tmp; |
127 | } |
128 | |
129 | constexpr reverse_iterator& operator--() { |
130 | ++current; |
131 | return *this; |
132 | } |
133 | |
134 | constexpr reverse_iterator operator--(int) { |
135 | reverse_iterator __tmp = *this; |
136 | ++current; |
137 | return __tmp; |
138 | } |
139 | |
140 | constexpr reverse_iterator operator+(difference_type __n) const { |
141 | return reverse_iterator(current - __n); |
142 | } |
143 | |
144 | constexpr reverse_iterator& operator+=(difference_type __n) { |
145 | current -= __n; |
146 | return *this; |
147 | } |
148 | |
149 | constexpr reverse_iterator operator-(difference_type __n) const { |
150 | return reverse_iterator(current + __n); |
151 | } |
152 | |
153 | constexpr reverse_iterator& operator-=(difference_type __n) { |
154 | current += __n; |
155 | return *this; |
156 | } |
157 | |
158 | constexpr reference operator[](difference_type __n) const { |
159 | return *(*this + __n); |
160 | } |
161 | |
162 | private: |
163 | template <typename _Tp> |
164 | static constexpr _Tp* _S_to_pointer(_Tp* __p) { |
165 | return __p; |
166 | } |
167 | |
168 | template <typename _Tp> |
169 | static constexpr pointer _S_to_pointer(_Tp __t) { |
170 | return __t.operator->(); |
171 | } |
172 | }; |
173 | |
174 | template <typename _Iterator> |
175 | inline constexpr bool operator==( |
176 | const reverse_iterator<_Iterator>& __x, |
177 | const reverse_iterator<_Iterator>& __y) { |
178 | return __x.base() == __y.base(); |
179 | } |
180 | |
181 | template <typename _Iterator> |
182 | inline constexpr bool operator<( |
183 | const reverse_iterator<_Iterator>& __x, |
184 | const reverse_iterator<_Iterator>& __y) { |
185 | return __y.base() < __x.base(); |
186 | } |
187 | |
188 | template <typename _Iterator> |
189 | inline constexpr bool operator!=( |
190 | const reverse_iterator<_Iterator>& __x, |
191 | const reverse_iterator<_Iterator>& __y) { |
192 | return !(__x == __y); |
193 | } |
194 | |
195 | template <typename _Iterator> |
196 | inline constexpr bool operator>( |
197 | const reverse_iterator<_Iterator>& __x, |
198 | const reverse_iterator<_Iterator>& __y) { |
199 | return __y < __x; |
200 | } |
201 | |
202 | template <typename _Iterator> |
203 | inline constexpr bool operator<=( |
204 | const reverse_iterator<_Iterator>& __x, |
205 | const reverse_iterator<_Iterator>& __y) { |
206 | return !(__y < __x); |
207 | } |
208 | |
209 | template <typename _Iterator> |
210 | inline constexpr bool operator>=( |
211 | const reverse_iterator<_Iterator>& __x, |
212 | const reverse_iterator<_Iterator>& __y) { |
213 | return !(__x < __y); |
214 | } |
215 | |
216 | template <typename _IteratorL, typename _IteratorR> |
217 | inline constexpr bool operator==( |
218 | const reverse_iterator<_IteratorL>& __x, |
219 | const reverse_iterator<_IteratorR>& __y) { |
220 | return __x.base() == __y.base(); |
221 | } |
222 | |
223 | template <typename _IteratorL, typename _IteratorR> |
224 | inline constexpr bool operator<( |
225 | const reverse_iterator<_IteratorL>& __x, |
226 | const reverse_iterator<_IteratorR>& __y) { |
227 | return __y.base() < __x.base(); |
228 | } |
229 | |
230 | template <typename _IteratorL, typename _IteratorR> |
231 | inline constexpr bool operator!=( |
232 | const reverse_iterator<_IteratorL>& __x, |
233 | const reverse_iterator<_IteratorR>& __y) { |
234 | return !(__x == __y); |
235 | } |
236 | |
237 | template <typename _IteratorL, typename _IteratorR> |
238 | inline constexpr bool operator>( |
239 | const reverse_iterator<_IteratorL>& __x, |
240 | const reverse_iterator<_IteratorR>& __y) { |
241 | return __y < __x; |
242 | } |
243 | |
244 | template <typename _IteratorL, typename _IteratorR> |
245 | inline constexpr bool operator<=( |
246 | const reverse_iterator<_IteratorL>& __x, |
247 | const reverse_iterator<_IteratorR>& __y) { |
248 | return !(__y < __x); |
249 | } |
250 | |
251 | template <typename _IteratorL, typename _IteratorR> |
252 | inline constexpr bool operator>=( |
253 | const reverse_iterator<_IteratorL>& __x, |
254 | const reverse_iterator<_IteratorR>& __y) { |
255 | return !(__x < __y); |
256 | } |
257 | |
258 | template <typename _IteratorL, typename _IteratorR> |
259 | inline constexpr decltype(auto) operator-( |
260 | const reverse_iterator<_IteratorL>& __x, |
261 | const reverse_iterator<_IteratorR>& __y) { |
262 | return __y.base() - __x.base(); |
263 | } |
264 | |
265 | template <typename _Iterator> |
266 | inline constexpr reverse_iterator<_Iterator> operator+( |
267 | typename reverse_iterator<_Iterator>::difference_type __n, |
268 | const reverse_iterator<_Iterator>& __x) { |
269 | return reverse_iterator<_Iterator>(__x.base() - __n); |
270 | } |
271 | |
272 | template <typename _Iterator> |
273 | inline constexpr reverse_iterator<_Iterator> __make_reverse_iterator( |
274 | _Iterator __i) { |
275 | return reverse_iterator<_Iterator>(__i); |
276 | } |
277 | |
278 | template <typename _Iterator> |
279 | inline constexpr reverse_iterator<_Iterator> make_reverse_iterator( |
280 | _Iterator __i) { |
281 | return reverse_iterator<_Iterator>(__i); |
282 | } |
283 | |
284 | template <typename _Iterator> |
285 | decltype(auto) __niter_base(reverse_iterator<_Iterator> __it) { |
286 | return __make_reverse_iterator(__niter_base(__it.base())); |
287 | } |
288 | |
289 | } // namespace c10 |
290 | |