xref: /freebsd-src/contrib/llvm-project/libcxx/include/__iterator/reverse_iterator.h (revision 0eae32dcef82f6f06de6419a0d623d7def0cc8f6)
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP___ITERATOR_REVERSE_ITERATOR_H
11 #define _LIBCPP___ITERATOR_REVERSE_ITERATOR_H
12 
13 #include <__config>
14 #include <__compare/compare_three_way_result.h>
15 #include <__compare/three_way_comparable.h>
16 #include <__iterator/iterator.h>
17 #include <__iterator/iterator_traits.h>
18 #include <__memory/addressof.h>
19 #include <type_traits>
20 
21 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
22 #pragma GCC system_header
23 #endif
24 
25 _LIBCPP_BEGIN_NAMESPACE_STD
26 
27 template <class _Tp, class = void>
28 struct __is_stashing_iterator : false_type {};
29 
30 template <class _Tp>
31 struct __is_stashing_iterator<_Tp, typename __void_t<typename _Tp::__stashing_iterator_tag>::type>
32   : true_type {};
33 
34 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
35 template <class _Iter>
36 class _LIBCPP_TEMPLATE_VIS reverse_iterator
37 #if _LIBCPP_STD_VER <= 14 || !defined(_LIBCPP_ABI_NO_ITERATOR_BASES)
38     : public iterator<typename iterator_traits<_Iter>::iterator_category,
39                       typename iterator_traits<_Iter>::value_type,
40                       typename iterator_traits<_Iter>::difference_type,
41                       typename iterator_traits<_Iter>::pointer,
42                       typename iterator_traits<_Iter>::reference>
43 #endif
44 {
45 _LIBCPP_SUPPRESS_DEPRECATED_POP
46 private:
47 #ifndef _LIBCPP_ABI_NO_ITERATOR_BASES
48     _Iter __t; // no longer used as of LWG #2360, not removed due to ABI break
49 #endif
50 
51     static_assert(!__is_stashing_iterator<_Iter>::value,
52       "The specified iterator type cannot be used with reverse_iterator; "
53       "Using stashing iterators with reverse_iterator causes undefined behavior");
54 
55 protected:
56     _Iter current;
57 public:
58     typedef _Iter                                            iterator_type;
59     typedef typename iterator_traits<_Iter>::difference_type difference_type;
60     typedef typename iterator_traits<_Iter>::reference       reference;
61     typedef typename iterator_traits<_Iter>::pointer         pointer;
62     typedef _If<__is_cpp17_random_access_iterator<_Iter>::value,
63         random_access_iterator_tag,
64         typename iterator_traits<_Iter>::iterator_category>  iterator_category;
65     typedef typename iterator_traits<_Iter>::value_type      value_type;
66 
67 #if _LIBCPP_STD_VER > 17
68     typedef _If<__is_cpp17_random_access_iterator<_Iter>::value,
69         random_access_iterator_tag,
70         bidirectional_iterator_tag>                          iterator_concept;
71 #endif
72 
73 #ifndef _LIBCPP_ABI_NO_ITERATOR_BASES
74     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
75     reverse_iterator() : __t(), current() {}
76 
77     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
78     explicit reverse_iterator(_Iter __x) : __t(__x), current(__x) {}
79 
80     template <class _Up, class = __enable_if_t<
81         !is_same<_Up, _Iter>::value && is_convertible<_Up const&, _Iter>::value
82     > >
83     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
84     reverse_iterator(const reverse_iterator<_Up>& __u)
85         : __t(__u.base()), current(__u.base())
86     { }
87 
88     template <class _Up, class = __enable_if_t<
89         !is_same<_Up, _Iter>::value &&
90         is_convertible<_Up const&, _Iter>::value &&
91         is_assignable<_Iter, _Up const&>::value
92     > >
93     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
94     reverse_iterator& operator=(const reverse_iterator<_Up>& __u) {
95         __t = current = __u.base();
96         return *this;
97     }
98 #else
99     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
100     reverse_iterator() : current() {}
101 
102     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
103     explicit reverse_iterator(_Iter __x) : current(__x) {}
104 
105     template <class _Up, class = __enable_if_t<
106         !is_same<_Up, _Iter>::value && is_convertible<_Up const&, _Iter>::value
107     > >
108     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
109     reverse_iterator(const reverse_iterator<_Up>& __u)
110         : current(__u.base())
111     { }
112 
113     template <class _Up, class = __enable_if_t<
114         !is_same<_Up, _Iter>::value &&
115         is_convertible<_Up const&, _Iter>::value &&
116         is_assignable<_Iter, _Up const&>::value
117     > >
118     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
119     reverse_iterator& operator=(const reverse_iterator<_Up>& __u) {
120         current = __u.base();
121         return *this;
122     }
123 #endif
124     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
125     _Iter base() const {return current;}
126     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
127     reference operator*() const {_Iter __tmp = current; return *--__tmp;}
128     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
129     pointer  operator->() const {return _VSTD::addressof(operator*());}
130     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
131     reverse_iterator& operator++() {--current; return *this;}
132     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
133     reverse_iterator  operator++(int) {reverse_iterator __tmp(*this); --current; return __tmp;}
134     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
135     reverse_iterator& operator--() {++current; return *this;}
136     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
137     reverse_iterator  operator--(int) {reverse_iterator __tmp(*this); ++current; return __tmp;}
138     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
139     reverse_iterator  operator+ (difference_type __n) const {return reverse_iterator(current - __n);}
140     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
141     reverse_iterator& operator+=(difference_type __n) {current -= __n; return *this;}
142     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
143     reverse_iterator  operator- (difference_type __n) const {return reverse_iterator(current + __n);}
144     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
145     reverse_iterator& operator-=(difference_type __n) {current += __n; return *this;}
146     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
147     reference         operator[](difference_type __n) const {return *(*this + __n);}
148 };
149 
150 template <class _Iter1, class _Iter2>
151 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
152 bool
153 operator==(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
154 {
155     return __x.base() == __y.base();
156 }
157 
158 template <class _Iter1, class _Iter2>
159 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
160 bool
161 operator<(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
162 {
163     return __x.base() > __y.base();
164 }
165 
166 template <class _Iter1, class _Iter2>
167 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
168 bool
169 operator!=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
170 {
171     return __x.base() != __y.base();
172 }
173 
174 template <class _Iter1, class _Iter2>
175 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
176 bool
177 operator>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
178 {
179     return __x.base() < __y.base();
180 }
181 
182 template <class _Iter1, class _Iter2>
183 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
184 bool
185 operator>=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
186 {
187     return __x.base() <= __y.base();
188 }
189 
190 template <class _Iter1, class _Iter2>
191 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
192 bool
193 operator<=(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
194 {
195     return __x.base() >= __y.base();
196 }
197 
198 #if _LIBCPP_STD_VER > 17 && !defined(_LIBCPP_HAS_NO_CONCEPTS)
199 template <class _Iter1, three_way_comparable_with<_Iter1> _Iter2>
200 _LIBCPP_HIDE_FROM_ABI constexpr
201 compare_three_way_result_t<_Iter1, _Iter2>
202 operator<=>(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
203 {
204     return __y.base() <=> __x.base();
205 }
206 #endif
207 
208 #ifndef _LIBCPP_CXX03_LANG
209 template <class _Iter1, class _Iter2>
210 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
211 auto
212 operator-(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
213 -> decltype(__y.base() - __x.base())
214 {
215     return __y.base() - __x.base();
216 }
217 #else
218 template <class _Iter1, class _Iter2>
219 inline _LIBCPP_INLINE_VISIBILITY
220 typename reverse_iterator<_Iter1>::difference_type
221 operator-(const reverse_iterator<_Iter1>& __x, const reverse_iterator<_Iter2>& __y)
222 {
223     return __y.base() - __x.base();
224 }
225 #endif
226 
227 template <class _Iter>
228 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
229 reverse_iterator<_Iter>
230 operator+(typename reverse_iterator<_Iter>::difference_type __n, const reverse_iterator<_Iter>& __x)
231 {
232     return reverse_iterator<_Iter>(__x.base() - __n);
233 }
234 
235 #if _LIBCPP_STD_VER > 11
236 template <class _Iter>
237 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX14
238 reverse_iterator<_Iter> make_reverse_iterator(_Iter __i)
239 {
240     return reverse_iterator<_Iter>(__i);
241 }
242 #endif
243 
244 _LIBCPP_END_NAMESPACE_STD
245 
246 #endif // _LIBCPP___ITERATOR_REVERSE_ITERATOR_H
247