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 16 namespace llvm { 17 18 /// \brief CRTP base class which implements the entire standard iterator facade 19 /// in terms of a minimal subset of the interface. 20 /// 21 /// Use this when it is reasonable to implement most of the iterator 22 /// functionality in terms of a core subset. If you need special behavior or 23 /// there are performance implications for this, you may want to override the 24 /// relevant members instead. 25 /// 26 /// Note, one abstraction that this does *not* provide is implementing 27 /// subtraction in terms of addition by negating the difference. Negation isn't 28 /// always information preserving, and I can see very reasonable iterator 29 /// designs where this doesn't work well. It doesn't really force much added 30 /// boilerplate anyways. 31 /// 32 /// Another abstraction that this doesn't provide is implementing increment in 33 /// terms of addition of one. These aren't equivalent for all iterator 34 /// categories, and respecting that adds a lot of complexity for little gain. 35 template <typename DerivedT, typename IteratorCategoryT, typename T, 36 typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *, 37 typename ReferenceT = T &> 38 class iterator_facade_base 39 : public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT, 40 ReferenceT> { 41 protected: 42 enum { 43 IsRandomAccess = 44 std::is_base_of<std::random_access_iterator_tag, IteratorCategoryT>::value, 45 IsBidirectional = 46 std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value, 47 }; 48 49 /// A proxy object for computing a reference via indirecting a copy of an 50 /// iterator. This is used in APIs which need to produce a reference via 51 /// indirection but for which the iterator object might be a temporary. The 52 /// proxy preserves the iterator internally and exposes the indirected 53 /// reference via a conversion operator. 54 class ReferenceProxy { 55 friend iterator_facade_base; 56 57 DerivedT I; 58 ReferenceProxy(DerivedT I)59 ReferenceProxy(DerivedT I) : I(std::move(I)) {} 60 61 public: ReferenceT()62 operator ReferenceT() const { return *I; } 63 }; 64 65 public: 66 DerivedT operator+(DifferenceTypeT n) const { 67 static_assert( 68 IsRandomAccess, 69 "The '+' operator is only defined for random access iterators."); 70 DerivedT tmp = *static_cast<const DerivedT *>(this); 71 tmp += n; 72 return tmp; 73 } 74 friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) { 75 static_assert( 76 IsRandomAccess, 77 "The '+' operator is only defined for random access iterators."); 78 return i + n; 79 } 80 DerivedT operator-(DifferenceTypeT n) const { 81 static_assert( 82 IsRandomAccess, 83 "The '-' operator is only defined for random access iterators."); 84 DerivedT tmp = *static_cast<const DerivedT *>(this); 85 tmp -= n; 86 return tmp; 87 } 88 89 DerivedT &operator++() { 90 return static_cast<DerivedT *>(this)->operator+=(1); 91 } 92 DerivedT operator++(int) { 93 DerivedT tmp = *static_cast<DerivedT *>(this); 94 ++*static_cast<DerivedT *>(this); 95 return tmp; 96 } 97 DerivedT &operator--() { 98 static_assert( 99 IsBidirectional, 100 "The decrement operator is only defined for bidirectional iterators."); 101 return static_cast<DerivedT *>(this)->operator-=(1); 102 } 103 DerivedT operator--(int) { 104 static_assert( 105 IsBidirectional, 106 "The decrement operator is only defined for bidirectional iterators."); 107 DerivedT tmp = *static_cast<DerivedT *>(this); 108 --*static_cast<DerivedT *>(this); 109 return tmp; 110 } 111 112 bool operator!=(const DerivedT &RHS) const { 113 return !static_cast<const DerivedT *>(this)->operator==(RHS); 114 } 115 116 bool operator>(const DerivedT &RHS) const { 117 static_assert( 118 IsRandomAccess, 119 "Relational operators are only defined for random access iterators."); 120 return !static_cast<const DerivedT *>(this)->operator<(RHS) && 121 !static_cast<const DerivedT *>(this)->operator==(RHS); 122 } 123 bool operator<=(const DerivedT &RHS) const { 124 static_assert( 125 IsRandomAccess, 126 "Relational operators are only defined for random access iterators."); 127 return !static_cast<const DerivedT *>(this)->operator>(RHS); 128 } 129 bool operator>=(const DerivedT &RHS) const { 130 static_assert( 131 IsRandomAccess, 132 "Relational operators are only defined for random access iterators."); 133 return !static_cast<const DerivedT *>(this)->operator<(RHS); 134 } 135 136 PointerT operator->() const { 137 return &static_cast<const DerivedT *>(this)->operator*(); 138 } 139 ReferenceProxy operator[](DifferenceTypeT n) const { 140 static_assert(IsRandomAccess, 141 "Subscripting is only defined for random access iterators."); 142 return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n)); 143 } 144 }; 145 146 /// \brief CRTP base class for adapting an iterator to a different type. 147 /// 148 /// This class can be used through CRTP to adapt one iterator into another. 149 /// Typically this is done through providing in the derived class a custom \c 150 /// operator* implementation. Other methods can be overridden as well. 151 template < 152 typename DerivedT, typename WrappedIteratorT, 153 typename IteratorCategoryT = 154 typename std::iterator_traits<WrappedIteratorT>::iterator_category, 155 typename T = typename std::iterator_traits<WrappedIteratorT>::value_type, 156 typename DifferenceTypeT = 157 typename std::iterator_traits<WrappedIteratorT>::difference_type, 158 typename PointerT = T *, typename ReferenceT = T &, 159 // Don't provide these, they are mostly to act as aliases below. 160 typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>> 161 class iterator_adaptor_base 162 : public iterator_facade_base<DerivedT, IteratorCategoryT, T, 163 DifferenceTypeT, PointerT, ReferenceT> { 164 typedef typename iterator_adaptor_base::iterator_facade_base BaseT; 165 166 protected: 167 WrappedIteratorT I; 168 169 iterator_adaptor_base() = default; 170 171 template <typename U> 172 explicit iterator_adaptor_base( 173 U &&u, 174 typename std::enable_if< 175 !std::is_base_of<typename std::remove_cv< 176 typename std::remove_reference<U>::type>::type, 177 DerivedT>::value, 178 int>::type = 0) I(std::forward<U &&> (u))179 : I(std::forward<U &&>(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 } 261 262 #endif 263