1 //===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef LLVM_ADT_ITERATOR_H 11 #define LLVM_ADT_ITERATOR_H 12 13 #include <cstddef> 14 #include <iterator> 15 #include <type_traits> 16 17 namespace llvm { 18 19 /// \brief CRTP base class which implements the entire standard iterator facade 20 /// in terms of a minimal subset of the interface. 21 /// 22 /// Use this when it is reasonable to implement most of the iterator 23 /// functionality in terms of a core subset. If you need special behavior or 24 /// there are performance implications for this, you may want to override the 25 /// relevant members instead. 26 /// 27 /// Note, one abstraction that this does *not* provide is implementing 28 /// subtraction in terms of addition by negating the difference. Negation isn't 29 /// always information preserving, and I can see very reasonable iterator 30 /// designs where this doesn't work well. It doesn't really force much added 31 /// boilerplate anyways. 32 /// 33 /// Another abstraction that this doesn't provide is implementing increment in 34 /// terms of addition of one. These aren't equivalent for all iterator 35 /// categories, and respecting that adds a lot of complexity for little gain. 36 template <typename DerivedT, typename IteratorCategoryT, typename T, 37 typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *, 38 typename ReferenceT = T &> 39 class iterator_facade_base 40 : public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT, 41 ReferenceT> { 42 protected: 43 enum { 44 IsRandomAccess = 45 std::is_base_of<std::random_access_iterator_tag, IteratorCategoryT>::value, 46 IsBidirectional = 47 std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value, 48 }; 49 50 /// A proxy object for computing a reference via indirecting a copy of an 51 /// iterator. This is used in APIs which need to produce a reference via 52 /// indirection but for which the iterator object might be a temporary. The 53 /// proxy preserves the iterator internally and exposes the indirected 54 /// reference via a conversion operator. 55 class ReferenceProxy { 56 friend iterator_facade_base; 57 58 DerivedT I; 59 ReferenceProxy(DerivedT I)60 ReferenceProxy(DerivedT I) : I(std::move(I)) {} 61 62 public: ReferenceT()63 operator ReferenceT() const { return *I; } 64 }; 65 66 public: 67 DerivedT operator+(DifferenceTypeT n) const { 68 static_assert( 69 IsRandomAccess, 70 "The '+' operator is only defined for random access iterators."); 71 DerivedT tmp = *static_cast<const DerivedT *>(this); 72 tmp += n; 73 return tmp; 74 } 75 friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) { 76 static_assert( 77 IsRandomAccess, 78 "The '+' operator is only defined for random access iterators."); 79 return i + n; 80 } 81 DerivedT operator-(DifferenceTypeT n) const { 82 static_assert( 83 IsRandomAccess, 84 "The '-' operator is only defined for random access iterators."); 85 DerivedT tmp = *static_cast<const DerivedT *>(this); 86 tmp -= n; 87 return tmp; 88 } 89 90 DerivedT &operator++() { 91 return static_cast<DerivedT *>(this)->operator+=(1); 92 } 93 DerivedT operator++(int) { 94 DerivedT tmp = *static_cast<DerivedT *>(this); 95 ++*static_cast<DerivedT *>(this); 96 return tmp; 97 } 98 DerivedT &operator--() { 99 static_assert( 100 IsBidirectional, 101 "The decrement operator is only defined for bidirectional iterators."); 102 return static_cast<DerivedT *>(this)->operator-=(1); 103 } 104 DerivedT operator--(int) { 105 static_assert( 106 IsBidirectional, 107 "The decrement operator is only defined for bidirectional iterators."); 108 DerivedT tmp = *static_cast<DerivedT *>(this); 109 --*static_cast<DerivedT *>(this); 110 return tmp; 111 } 112 113 bool operator!=(const DerivedT &RHS) const { 114 return !static_cast<const DerivedT *>(this)->operator==(RHS); 115 } 116 117 bool operator>(const DerivedT &RHS) const { 118 static_assert( 119 IsRandomAccess, 120 "Relational operators are only defined for random access iterators."); 121 return !static_cast<const DerivedT *>(this)->operator<(RHS) && 122 !static_cast<const DerivedT *>(this)->operator==(RHS); 123 } 124 bool operator<=(const DerivedT &RHS) const { 125 static_assert( 126 IsRandomAccess, 127 "Relational operators are only defined for random access iterators."); 128 return !static_cast<const DerivedT *>(this)->operator>(RHS); 129 } 130 bool operator>=(const DerivedT &RHS) const { 131 static_assert( 132 IsRandomAccess, 133 "Relational operators are only defined for random access iterators."); 134 return !static_cast<const DerivedT *>(this)->operator<(RHS); 135 } 136 137 PointerT operator->() const { 138 return &static_cast<const DerivedT *>(this)->operator*(); 139 } 140 ReferenceProxy operator[](DifferenceTypeT n) const { 141 static_assert(IsRandomAccess, 142 "Subscripting is only defined for random access iterators."); 143 return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n)); 144 } 145 }; 146 147 /// \brief CRTP base class for adapting an iterator to a different type. 148 /// 149 /// This class can be used through CRTP to adapt one iterator into another. 150 /// Typically this is done through providing in the derived class a custom \c 151 /// operator* implementation. Other methods can be overridden as well. 152 template < 153 typename DerivedT, typename WrappedIteratorT, 154 typename IteratorCategoryT = 155 typename std::iterator_traits<WrappedIteratorT>::iterator_category, 156 typename T = typename std::iterator_traits<WrappedIteratorT>::value_type, 157 typename DifferenceTypeT = 158 typename std::iterator_traits<WrappedIteratorT>::difference_type, 159 typename PointerT = typename std::conditional< 160 std::is_same<T, typename std::iterator_traits< 161 WrappedIteratorT>::value_type>::value, 162 typename std::iterator_traits<WrappedIteratorT>::pointer, T *>::type, 163 typename ReferenceT = typename std::conditional< 164 std::is_same<T, typename std::iterator_traits< 165 WrappedIteratorT>::value_type>::value, 166 typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type, 167 // Don't provide these, they are mostly to act as aliases below. 168 typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>> 169 class iterator_adaptor_base 170 : public iterator_facade_base<DerivedT, IteratorCategoryT, T, 171 DifferenceTypeT, PointerT, ReferenceT> { 172 typedef typename iterator_adaptor_base::iterator_facade_base BaseT; 173 174 protected: 175 WrappedIteratorT I; 176 177 iterator_adaptor_base() = default; 178 iterator_adaptor_base(WrappedIteratorT u)179 explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {} 180 wrapped()181 const WrappedIteratorT &wrapped() const { return I; } 182 183 public: 184 typedef DifferenceTypeT difference_type; 185 186 DerivedT &operator+=(difference_type n) { 187 static_assert( 188 BaseT::IsRandomAccess, 189 "The '+=' operator is only defined for random access iterators."); 190 I += n; 191 return *static_cast<DerivedT *>(this); 192 } 193 DerivedT &operator-=(difference_type n) { 194 static_assert( 195 BaseT::IsRandomAccess, 196 "The '-=' operator is only defined for random access iterators."); 197 I -= n; 198 return *static_cast<DerivedT *>(this); 199 } 200 using BaseT::operator-; 201 difference_type operator-(const DerivedT &RHS) const { 202 static_assert( 203 BaseT::IsRandomAccess, 204 "The '-' operator is only defined for random access iterators."); 205 return I - RHS.I; 206 } 207 208 // We have to explicitly provide ++ and -- rather than letting the facade 209 // forward to += because WrappedIteratorT might not support +=. 210 using BaseT::operator++; 211 DerivedT &operator++() { 212 ++I; 213 return *static_cast<DerivedT *>(this); 214 } 215 using BaseT::operator--; 216 DerivedT &operator--() { 217 static_assert( 218 BaseT::IsBidirectional, 219 "The decrement operator is only defined for bidirectional iterators."); 220 --I; 221 return *static_cast<DerivedT *>(this); 222 } 223 224 bool operator==(const DerivedT &RHS) const { return I == RHS.I; } 225 bool operator<(const DerivedT &RHS) const { 226 static_assert( 227 BaseT::IsRandomAccess, 228 "Relational operators are only defined for random access iterators."); 229 return I < RHS.I; 230 } 231 232 ReferenceT operator*() const { return *I; } 233 }; 234 235 /// \brief An iterator type that allows iterating over the pointees via some 236 /// other iterator. 237 /// 238 /// The typical usage of this is to expose a type that iterates over Ts, but 239 /// which is implemented with some iterator over T*s: 240 /// 241 /// \code 242 /// typedef pointee_iterator<SmallVectorImpl<T *>::iterator> iterator; 243 /// \endcode 244 template <typename WrappedIteratorT, 245 typename T = typename std::remove_reference< 246 decltype(**std::declval<WrappedIteratorT>())>::type> 247 struct pointee_iterator 248 : iterator_adaptor_base< 249 pointee_iterator<WrappedIteratorT>, WrappedIteratorT, 250 typename std::iterator_traits<WrappedIteratorT>::iterator_category, 251 T> { 252 pointee_iterator() = default; 253 template <typename U> pointee_iteratorpointee_iterator254 pointee_iterator(U &&u) 255 : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {} 256 257 T &operator*() const { return **this->I; } 258 }; 259 260 template <typename WrappedIteratorT, 261 typename T = decltype(&*std::declval<WrappedIteratorT>())> 262 class pointer_iterator 263 : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT>, 264 WrappedIteratorT, T> { 265 mutable T Ptr; 266 267 public: 268 pointer_iterator() = default; 269 pointer_iterator(WrappedIteratorT u)270 explicit pointer_iterator(WrappedIteratorT u) 271 : pointer_iterator::iterator_adaptor_base(std::move(u)) {} 272 273 T &operator*() { return Ptr = &*this->I; } 274 const T &operator*() const { return Ptr = &*this->I; } 275 }; 276 277 } // end namespace llvm 278 279 #endif // LLVM_ADT_ITERATOR_H 280