iterator.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #ifndef LLVM_ADT_ITERATOR_H
  14. #define LLVM_ADT_ITERATOR_H
  15. #include "llvm/ADT/iterator_range.h"
  16. #include <cstddef>
  17. #include <iterator>
  18. #include <type_traits>
  19. #include <utility>
  20. namespace llvm {
  21. /// CRTP base class which implements the entire standard iterator facade
  22. /// in terms of a minimal subset of the interface.
  23. ///
  24. /// Use this when it is reasonable to implement most of the iterator
  25. /// functionality in terms of a core subset. If you need special behavior or
  26. /// there are performance implications for this, you may want to override the
  27. /// relevant members instead.
  28. ///
  29. /// Note, one abstraction that this does *not* provide is implementing
  30. /// subtraction in terms of addition by negating the difference. Negation isn't
  31. /// always information preserving, and I can see very reasonable iterator
  32. /// designs where this doesn't work well. It doesn't really force much added
  33. /// boilerplate anyways.
  34. ///
  35. /// Another abstraction that this doesn't provide is implementing increment in
  36. /// terms of addition of one. These aren't equivalent for all iterator
  37. /// categories, and respecting that adds a lot of complexity for little gain.
  38. ///
  39. /// Iterators are expected to have const rules analogous to pointers, with a
  40. /// single, const-qualified operator*() that returns ReferenceT. This matches
  41. /// the second and third pointers in the following example:
  42. /// \code
  43. /// int Value;
  44. /// { int *I = &Value; } // ReferenceT 'int&'
  45. /// { int *const I = &Value; } // ReferenceT 'int&'; const
  46. /// { const int *I = &Value; } // ReferenceT 'const int&'
  47. /// { const int *const I = &Value; } // ReferenceT 'const int&'; const
  48. /// \endcode
  49. /// If an iterator facade returns a handle to its own state, then T (and
  50. /// PointerT and ReferenceT) should usually be const-qualified. Otherwise, if
  51. /// clients are expected to modify the handle itself, the field can be declared
  52. /// mutable or use const_cast.
  53. ///
  54. /// Classes wishing to use `iterator_facade_base` should implement the following
  55. /// methods:
  56. ///
  57. /// Forward Iterators:
  58. /// (All of the following methods)
  59. /// - DerivedT &operator=(const DerivedT &R);
  60. /// - bool operator==(const DerivedT &R) const;
  61. /// - T &operator*() const;
  62. /// - DerivedT &operator++();
  63. ///
  64. /// Bidirectional Iterators:
  65. /// (All methods of forward iterators, plus the following)
  66. /// - DerivedT &operator--();
  67. ///
  68. /// Random-access Iterators:
  69. /// (All methods of bidirectional iterators excluding the following)
  70. /// - DerivedT &operator++();
  71. /// - DerivedT &operator--();
  72. /// (and plus the following)
  73. /// - bool operator<(const DerivedT &RHS) const;
  74. /// - DifferenceTypeT operator-(const DerivedT &R) const;
  75. /// - DerivedT &operator+=(DifferenceTypeT N);
  76. /// - DerivedT &operator-=(DifferenceTypeT N);
  77. ///
  78. template <typename DerivedT, typename IteratorCategoryT, typename T,
  79. typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *,
  80. typename ReferenceT = T &>
  81. class iterator_facade_base {
  82. public:
  83. using iterator_category = IteratorCategoryT;
  84. using value_type = T;
  85. using difference_type = DifferenceTypeT;
  86. using pointer = PointerT;
  87. using reference = ReferenceT;
  88. protected:
  89. enum {
  90. IsRandomAccess = std::is_base_of<std::random_access_iterator_tag,
  91. IteratorCategoryT>::value,
  92. IsBidirectional = std::is_base_of<std::bidirectional_iterator_tag,
  93. IteratorCategoryT>::value,
  94. };
  95. /// A proxy object for computing a reference via indirecting a copy of an
  96. /// iterator. This is used in APIs which need to produce a reference via
  97. /// indirection but for which the iterator object might be a temporary. The
  98. /// proxy preserves the iterator internally and exposes the indirected
  99. /// reference via a conversion operator.
  100. class ReferenceProxy {
  101. friend iterator_facade_base;
  102. DerivedT I;
  103. ReferenceProxy(DerivedT I) : I(std::move(I)) {}
  104. public:
  105. operator ReferenceT() const { return *I; }
  106. };
  107. /// A proxy object for computing a pointer via indirecting a copy of a
  108. /// reference. This is used in APIs which need to produce a pointer but for
  109. /// which the reference might be a temporary. The proxy preserves the
  110. /// reference internally and exposes the pointer via a arrow operator.
  111. class PointerProxy {
  112. friend iterator_facade_base;
  113. ReferenceT R;
  114. template <typename RefT>
  115. PointerProxy(RefT &&R) : R(std::forward<RefT>(R)) {}
  116. public:
  117. PointerT operator->() const { return &R; }
  118. };
  119. public:
  120. DerivedT operator+(DifferenceTypeT n) const {
  121. static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
  122. "Must pass the derived type to this template!");
  123. static_assert(
  124. IsRandomAccess,
  125. "The '+' operator is only defined for random access iterators.");
  126. DerivedT tmp = *static_cast<const DerivedT *>(this);
  127. tmp += n;
  128. return tmp;
  129. }
  130. friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) {
  131. static_assert(
  132. IsRandomAccess,
  133. "The '+' operator is only defined for random access iterators.");
  134. return i + n;
  135. }
  136. DerivedT operator-(DifferenceTypeT n) const {
  137. static_assert(
  138. IsRandomAccess,
  139. "The '-' operator is only defined for random access iterators.");
  140. DerivedT tmp = *static_cast<const DerivedT *>(this);
  141. tmp -= n;
  142. return tmp;
  143. }
  144. DerivedT &operator++() {
  145. static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
  146. "Must pass the derived type to this template!");
  147. return static_cast<DerivedT *>(this)->operator+=(1);
  148. }
  149. DerivedT operator++(int) {
  150. DerivedT tmp = *static_cast<DerivedT *>(this);
  151. ++*static_cast<DerivedT *>(this);
  152. return tmp;
  153. }
  154. DerivedT &operator--() {
  155. static_assert(
  156. IsBidirectional,
  157. "The decrement operator is only defined for bidirectional iterators.");
  158. return static_cast<DerivedT *>(this)->operator-=(1);
  159. }
  160. DerivedT operator--(int) {
  161. static_assert(
  162. IsBidirectional,
  163. "The decrement operator is only defined for bidirectional iterators.");
  164. DerivedT tmp = *static_cast<DerivedT *>(this);
  165. --*static_cast<DerivedT *>(this);
  166. return tmp;
  167. }
  168. #ifndef __cpp_impl_three_way_comparison
  169. bool operator!=(const DerivedT &RHS) const {
  170. return !(static_cast<const DerivedT &>(*this) == RHS);
  171. }
  172. #endif
  173. bool operator>(const DerivedT &RHS) const {
  174. static_assert(
  175. IsRandomAccess,
  176. "Relational operators are only defined for random access iterators.");
  177. return !(static_cast<const DerivedT &>(*this) < RHS) &&
  178. !(static_cast<const DerivedT &>(*this) == RHS);
  179. }
  180. bool operator<=(const DerivedT &RHS) const {
  181. static_assert(
  182. IsRandomAccess,
  183. "Relational operators are only defined for random access iterators.");
  184. return !(static_cast<const DerivedT &>(*this) > RHS);
  185. }
  186. bool operator>=(const DerivedT &RHS) const {
  187. static_assert(
  188. IsRandomAccess,
  189. "Relational operators are only defined for random access iterators.");
  190. return !(static_cast<const DerivedT &>(*this) < RHS);
  191. }
  192. PointerProxy operator->() const {
  193. return static_cast<const DerivedT *>(this)->operator*();
  194. }
  195. ReferenceProxy operator[](DifferenceTypeT n) const {
  196. static_assert(IsRandomAccess,
  197. "Subscripting is only defined for random access iterators.");
  198. return static_cast<const DerivedT *>(this)->operator+(n);
  199. }
  200. };
  201. /// CRTP base class for adapting an iterator to a different type.
  202. ///
  203. /// This class can be used through CRTP to adapt one iterator into another.
  204. /// Typically this is done through providing in the derived class a custom \c
  205. /// operator* implementation. Other methods can be overridden as well.
  206. template <
  207. typename DerivedT, typename WrappedIteratorT,
  208. typename IteratorCategoryT =
  209. typename std::iterator_traits<WrappedIteratorT>::iterator_category,
  210. typename T = typename std::iterator_traits<WrappedIteratorT>::value_type,
  211. typename DifferenceTypeT =
  212. typename std::iterator_traits<WrappedIteratorT>::difference_type,
  213. typename PointerT = std::conditional_t<
  214. std::is_same<T, typename std::iterator_traits<
  215. WrappedIteratorT>::value_type>::value,
  216. typename std::iterator_traits<WrappedIteratorT>::pointer, T *>,
  217. typename ReferenceT = std::conditional_t<
  218. std::is_same<T, typename std::iterator_traits<
  219. WrappedIteratorT>::value_type>::value,
  220. typename std::iterator_traits<WrappedIteratorT>::reference, T &>>
  221. class iterator_adaptor_base
  222. : public iterator_facade_base<DerivedT, IteratorCategoryT, T,
  223. DifferenceTypeT, PointerT, ReferenceT> {
  224. using BaseT = typename iterator_adaptor_base::iterator_facade_base;
  225. protected:
  226. WrappedIteratorT I;
  227. iterator_adaptor_base() = default;
  228. explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {
  229. static_assert(std::is_base_of<iterator_adaptor_base, DerivedT>::value,
  230. "Must pass the derived type to this template!");
  231. }
  232. const WrappedIteratorT &wrapped() const { return I; }
  233. public:
  234. using difference_type = DifferenceTypeT;
  235. DerivedT &operator+=(difference_type n) {
  236. static_assert(
  237. BaseT::IsRandomAccess,
  238. "The '+=' operator is only defined for random access iterators.");
  239. I += n;
  240. return *static_cast<DerivedT *>(this);
  241. }
  242. DerivedT &operator-=(difference_type n) {
  243. static_assert(
  244. BaseT::IsRandomAccess,
  245. "The '-=' operator is only defined for random access iterators.");
  246. I -= n;
  247. return *static_cast<DerivedT *>(this);
  248. }
  249. using BaseT::operator-;
  250. difference_type operator-(const DerivedT &RHS) const {
  251. static_assert(
  252. BaseT::IsRandomAccess,
  253. "The '-' operator is only defined for random access iterators.");
  254. return I - RHS.I;
  255. }
  256. // We have to explicitly provide ++ and -- rather than letting the facade
  257. // forward to += because WrappedIteratorT might not support +=.
  258. using BaseT::operator++;
  259. DerivedT &operator++() {
  260. ++I;
  261. return *static_cast<DerivedT *>(this);
  262. }
  263. using BaseT::operator--;
  264. DerivedT &operator--() {
  265. static_assert(
  266. BaseT::IsBidirectional,
  267. "The decrement operator is only defined for bidirectional iterators.");
  268. --I;
  269. return *static_cast<DerivedT *>(this);
  270. }
  271. friend bool operator==(const iterator_adaptor_base &LHS,
  272. const iterator_adaptor_base &RHS) {
  273. return LHS.I == RHS.I;
  274. }
  275. friend bool operator<(const iterator_adaptor_base &LHS,
  276. const iterator_adaptor_base &RHS) {
  277. static_assert(
  278. BaseT::IsRandomAccess,
  279. "Relational operators are only defined for random access iterators.");
  280. return LHS.I < RHS.I;
  281. }
  282. ReferenceT operator*() const { return *I; }
  283. };
  284. /// An iterator type that allows iterating over the pointees via some
  285. /// other iterator.
  286. ///
  287. /// The typical usage of this is to expose a type that iterates over Ts, but
  288. /// which is implemented with some iterator over T*s:
  289. ///
  290. /// \code
  291. /// using iterator = pointee_iterator<SmallVectorImpl<T *>::iterator>;
  292. /// \endcode
  293. template <typename WrappedIteratorT,
  294. typename T = std::remove_reference_t<decltype(
  295. **std::declval<WrappedIteratorT>())>>
  296. struct pointee_iterator
  297. : iterator_adaptor_base<
  298. pointee_iterator<WrappedIteratorT, T>, WrappedIteratorT,
  299. typename std::iterator_traits<WrappedIteratorT>::iterator_category,
  300. T> {
  301. pointee_iterator() = default;
  302. template <typename U>
  303. pointee_iterator(U &&u)
  304. : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {}
  305. T &operator*() const { return **this->I; }
  306. };
  307. template <typename RangeT, typename WrappedIteratorT =
  308. decltype(std::begin(std::declval<RangeT>()))>
  309. iterator_range<pointee_iterator<WrappedIteratorT>>
  310. make_pointee_range(RangeT &&Range) {
  311. using PointeeIteratorT = pointee_iterator<WrappedIteratorT>;
  312. return make_range(PointeeIteratorT(std::begin(std::forward<RangeT>(Range))),
  313. PointeeIteratorT(std::end(std::forward<RangeT>(Range))));
  314. }
  315. template <typename WrappedIteratorT,
  316. typename T = decltype(&*std::declval<WrappedIteratorT>())>
  317. class pointer_iterator
  318. : public iterator_adaptor_base<
  319. pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT,
  320. typename std::iterator_traits<WrappedIteratorT>::iterator_category,
  321. T> {
  322. mutable T Ptr;
  323. public:
  324. pointer_iterator() = default;
  325. explicit pointer_iterator(WrappedIteratorT u)
  326. : pointer_iterator::iterator_adaptor_base(std::move(u)) {}
  327. T &operator*() const { return Ptr = &*this->I; }
  328. };
  329. template <typename RangeT, typename WrappedIteratorT =
  330. decltype(std::begin(std::declval<RangeT>()))>
  331. iterator_range<pointer_iterator<WrappedIteratorT>>
  332. make_pointer_range(RangeT &&Range) {
  333. using PointerIteratorT = pointer_iterator<WrappedIteratorT>;
  334. return make_range(PointerIteratorT(std::begin(std::forward<RangeT>(Range))),
  335. PointerIteratorT(std::end(std::forward<RangeT>(Range))));
  336. }
  337. template <typename WrappedIteratorT,
  338. typename T1 = std::remove_reference_t<decltype(
  339. **std::declval<WrappedIteratorT>())>,
  340. typename T2 = std::add_pointer_t<T1>>
  341. using raw_pointer_iterator =
  342. pointer_iterator<pointee_iterator<WrappedIteratorT, T1>, T2>;
  343. } // end namespace llvm
  344. #endif // LLVM_ADT_ITERATOR_H
  345. #ifdef __GNUC__
  346. #pragma GCC diagnostic pop
  347. #endif