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
61namespace c10 {
62
63template <typename _Iterator>
64class 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
174template <typename _Iterator>
175inline constexpr bool operator==(
176 const reverse_iterator<_Iterator>& __x,
177 const reverse_iterator<_Iterator>& __y) {
178 return __x.base() == __y.base();
179}
180
181template <typename _Iterator>
182inline constexpr bool operator<(
183 const reverse_iterator<_Iterator>& __x,
184 const reverse_iterator<_Iterator>& __y) {
185 return __y.base() < __x.base();
186}
187
188template <typename _Iterator>
189inline constexpr bool operator!=(
190 const reverse_iterator<_Iterator>& __x,
191 const reverse_iterator<_Iterator>& __y) {
192 return !(__x == __y);
193}
194
195template <typename _Iterator>
196inline constexpr bool operator>(
197 const reverse_iterator<_Iterator>& __x,
198 const reverse_iterator<_Iterator>& __y) {
199 return __y < __x;
200}
201
202template <typename _Iterator>
203inline constexpr bool operator<=(
204 const reverse_iterator<_Iterator>& __x,
205 const reverse_iterator<_Iterator>& __y) {
206 return !(__y < __x);
207}
208
209template <typename _Iterator>
210inline constexpr bool operator>=(
211 const reverse_iterator<_Iterator>& __x,
212 const reverse_iterator<_Iterator>& __y) {
213 return !(__x < __y);
214}
215
216template <typename _IteratorL, typename _IteratorR>
217inline constexpr bool operator==(
218 const reverse_iterator<_IteratorL>& __x,
219 const reverse_iterator<_IteratorR>& __y) {
220 return __x.base() == __y.base();
221}
222
223template <typename _IteratorL, typename _IteratorR>
224inline constexpr bool operator<(
225 const reverse_iterator<_IteratorL>& __x,
226 const reverse_iterator<_IteratorR>& __y) {
227 return __y.base() < __x.base();
228}
229
230template <typename _IteratorL, typename _IteratorR>
231inline constexpr bool operator!=(
232 const reverse_iterator<_IteratorL>& __x,
233 const reverse_iterator<_IteratorR>& __y) {
234 return !(__x == __y);
235}
236
237template <typename _IteratorL, typename _IteratorR>
238inline constexpr bool operator>(
239 const reverse_iterator<_IteratorL>& __x,
240 const reverse_iterator<_IteratorR>& __y) {
241 return __y < __x;
242}
243
244template <typename _IteratorL, typename _IteratorR>
245inline constexpr bool operator<=(
246 const reverse_iterator<_IteratorL>& __x,
247 const reverse_iterator<_IteratorR>& __y) {
248 return !(__y < __x);
249}
250
251template <typename _IteratorL, typename _IteratorR>
252inline constexpr bool operator>=(
253 const reverse_iterator<_IteratorL>& __x,
254 const reverse_iterator<_IteratorR>& __y) {
255 return !(__x < __y);
256}
257
258template <typename _IteratorL, typename _IteratorR>
259inline constexpr decltype(auto) operator-(
260 const reverse_iterator<_IteratorL>& __x,
261 const reverse_iterator<_IteratorR>& __y) {
262 return __y.base() - __x.base();
263}
264
265template <typename _Iterator>
266inline 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
272template <typename _Iterator>
273inline constexpr reverse_iterator<_Iterator> __make_reverse_iterator(
274 _Iterator __i) {
275 return reverse_iterator<_Iterator>(__i);
276}
277
278template <typename _Iterator>
279inline constexpr reverse_iterator<_Iterator> make_reverse_iterator(
280 _Iterator __i) {
281 return reverse_iterator<_Iterator>(__i);
282}
283
284template <typename _Iterator>
285decltype(auto) __niter_base(reverse_iterator<_Iterator> __it) {
286 return __make_reverse_iterator(__niter_base(__it.base()));
287}
288
289} // namespace c10
290