10 #ifndef WPIUTIL_WPI_ITERATOR_H
11 #define WPIUTIL_WPI_ITERATOR_H
17 #include <type_traits>
65 template <
typename DerivedT,
typename IteratorCategoryT,
typename T,
66 typename DifferenceTypeT = std::ptrdiff_t,
typename PointerT = T *,
67 typename ReferenceT = T &>
69 :
public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT,
73 IsRandomAccess = std::is_base_of<std::random_access_iterator_tag,
74 IteratorCategoryT>::value,
75 IsBidirectional = std::is_base_of<std::bidirectional_iterator_tag,
76 IteratorCategoryT>::value,
92 operator ReferenceT()
const {
return *I; }
96 DerivedT operator+(DifferenceTypeT n)
const {
97 static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
98 "Must pass the derived type to this template!");
101 "The '+' operator is only defined for random access iterators.");
102 DerivedT tmp = *static_cast<const DerivedT *>(
this);
106 friend DerivedT operator+(DifferenceTypeT n,
const DerivedT &i) {
109 "The '+' operator is only defined for random access iterators.");
112 DerivedT operator-(DifferenceTypeT n)
const {
115 "The '-' operator is only defined for random access iterators.");
116 DerivedT tmp = *static_cast<const DerivedT *>(
this);
121 DerivedT &operator++() {
122 static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
123 "Must pass the derived type to this template!");
124 return static_cast<DerivedT *>(
this)->operator+=(1);
126 DerivedT operator++(
int) {
127 DerivedT tmp = *static_cast<DerivedT *>(
this);
128 ++*static_cast<DerivedT *>(
this);
131 DerivedT &operator--() {
134 "The decrement operator is only defined for bidirectional iterators.");
135 return static_cast<DerivedT *>(
this)->operator-=(1);
137 DerivedT operator--(
int) {
140 "The decrement operator is only defined for bidirectional iterators.");
141 DerivedT tmp = *static_cast<DerivedT *>(
this);
142 --*static_cast<DerivedT *>(
this);
146 bool operator!=(
const DerivedT &RHS)
const {
147 return !static_cast<const DerivedT *>(
this)->operator==(RHS);
150 bool operator>(
const DerivedT &RHS)
const {
153 "Relational operators are only defined for random access iterators.");
154 return !static_cast<const DerivedT *>(
this)->operator<(RHS) &&
155 !static_cast<const DerivedT *>(
this)->operator==(RHS);
157 bool operator<=(
const DerivedT &RHS)
const {
160 "Relational operators are only defined for random access iterators.");
161 return !static_cast<const DerivedT *>(
this)->operator>(RHS);
163 bool operator>=(
const DerivedT &RHS)
const {
166 "Relational operators are only defined for random access iterators.");
167 return !static_cast<const DerivedT *>(
this)->operator<(RHS);
170 PointerT operator->() {
return &static_cast<DerivedT *>(
this)->operator*(); }
171 PointerT operator->()
const {
172 return &static_cast<const DerivedT *>(
this)->operator*();
174 ReferenceProxy operator[](DifferenceTypeT n) {
175 static_assert(IsRandomAccess,
176 "Subscripting is only defined for random access iterators.");
177 return ReferenceProxy(static_cast<DerivedT *>(
this)->
operator+(n));
179 ReferenceProxy operator[](DifferenceTypeT n)
const {
180 static_assert(IsRandomAccess,
181 "Subscripting is only defined for random access iterators.");
182 return ReferenceProxy(static_cast<const DerivedT *>(
this)->
operator+(n));
192 typename DerivedT,
typename WrappedIteratorT,
193 typename IteratorCategoryT =
194 typename std::iterator_traits<WrappedIteratorT>::iterator_category,
195 typename T =
typename std::iterator_traits<WrappedIteratorT>::value_type,
196 typename DifferenceTypeT =
197 typename std::iterator_traits<WrappedIteratorT>::difference_type,
198 typename PointerT =
typename std::conditional<
199 std::is_same<T,
typename std::iterator_traits<
200 WrappedIteratorT>::value_type>::value,
201 typename std::iterator_traits<WrappedIteratorT>::pointer, T *>::type,
202 typename ReferenceT =
typename std::conditional<
203 std::is_same<T,
typename std::iterator_traits<
204 WrappedIteratorT>::value_type>::value,
205 typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type>
208 DifferenceTypeT, PointerT, ReferenceT> {
209 using BaseT =
typename iterator_adaptor_base::iterator_facade_base;
217 static_assert(std::is_base_of<iterator_adaptor_base, DerivedT>::value,
218 "Must pass the derived type to this template!");
221 const WrappedIteratorT &wrapped()
const {
return I; }
224 using difference_type = DifferenceTypeT;
226 DerivedT &operator+=(difference_type n) {
228 BaseT::IsRandomAccess,
229 "The '+=' operator is only defined for random access iterators.");
231 return *static_cast<DerivedT *>(
this);
233 DerivedT &operator-=(difference_type n) {
235 BaseT::IsRandomAccess,
236 "The '-=' operator is only defined for random access iterators.");
238 return *static_cast<DerivedT *>(
this);
240 using BaseT::operator-;
241 difference_type operator-(
const DerivedT &RHS)
const {
243 BaseT::IsRandomAccess,
244 "The '-' operator is only defined for random access iterators.");
250 using BaseT::operator++;
251 DerivedT &operator++() {
253 return *static_cast<DerivedT *>(
this);
255 using BaseT::operator--;
256 DerivedT &operator--() {
258 BaseT::IsBidirectional,
259 "The decrement operator is only defined for bidirectional iterators.");
261 return *static_cast<DerivedT *>(
this);
264 bool operator==(
const DerivedT &RHS)
const {
return I == RHS.I; }
265 bool operator<(
const DerivedT &RHS)
const {
267 BaseT::IsRandomAccess,
268 "Relational operators are only defined for random access iterators.");
272 ReferenceT operator*()
const {
return *I; }
284 template <
typename WrappedIteratorT,
285 typename T =
typename std::remove_reference<
286 decltype(**std::declval<WrappedIteratorT>())>::type>
289 pointee_iterator<WrappedIteratorT, T>, WrappedIteratorT,
290 typename std::iterator_traits<WrappedIteratorT>::iterator_category,
293 template <
typename U>
295 : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {}
297 T &operator*()
const {
return **this->I; }
300 template <
typename RangeT,
typename WrappedIteratorT =
301 decltype(std::begin(std::declval<RangeT>()))>
303 make_pointee_range(RangeT &&Range) {
305 return make_range(PointeeIteratorT(std::begin(std::forward<RangeT>(Range))),
306 PointeeIteratorT(std::end(std::forward<RangeT>(Range))));
309 template <
typename WrappedIteratorT,
310 typename T = decltype(&*std::declval<WrappedIteratorT>())>
313 pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT,
314 typename std::iterator_traits<WrappedIteratorT>::iterator_category,
322 : pointer_iterator::iterator_adaptor_base(std::move(u)) {}
324 T &operator*() {
return Ptr = &*this->I; }
325 const T &operator*()
const {
return Ptr = &*this->I; }
328 template <
typename RangeT,
typename WrappedIteratorT =
329 decltype(std::begin(std::declval<RangeT>()))>
331 make_pointer_range(RangeT &&Range) {
333 return make_range(PointerIteratorT(std::begin(std::forward<RangeT>(Range))),
334 PointerIteratorT(std::end(std::forward<RangeT>(Range))));
339 #endif // LLVM_ADT_ITERATOR_H