xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ADT/iterator.h (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
10b57cec5SDimitry Andric //===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_ADT_ITERATOR_H
100b57cec5SDimitry Andric #define LLVM_ADT_ITERATOR_H
110b57cec5SDimitry Andric 
120b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
130b57cec5SDimitry Andric #include <cstddef>
140b57cec5SDimitry Andric #include <iterator>
150b57cec5SDimitry Andric #include <type_traits>
160b57cec5SDimitry Andric #include <utility>
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric namespace llvm {
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric /// CRTP base class which implements the entire standard iterator facade
210b57cec5SDimitry Andric /// in terms of a minimal subset of the interface.
220b57cec5SDimitry Andric ///
230b57cec5SDimitry Andric /// Use this when it is reasonable to implement most of the iterator
240b57cec5SDimitry Andric /// functionality in terms of a core subset. If you need special behavior or
250b57cec5SDimitry Andric /// there are performance implications for this, you may want to override the
260b57cec5SDimitry Andric /// relevant members instead.
270b57cec5SDimitry Andric ///
280b57cec5SDimitry Andric /// Note, one abstraction that this does *not* provide is implementing
290b57cec5SDimitry Andric /// subtraction in terms of addition by negating the difference. Negation isn't
300b57cec5SDimitry Andric /// always information preserving, and I can see very reasonable iterator
310b57cec5SDimitry Andric /// designs where this doesn't work well. It doesn't really force much added
320b57cec5SDimitry Andric /// boilerplate anyways.
330b57cec5SDimitry Andric ///
340b57cec5SDimitry Andric /// Another abstraction that this doesn't provide is implementing increment in
350b57cec5SDimitry Andric /// terms of addition of one. These aren't equivalent for all iterator
360b57cec5SDimitry Andric /// categories, and respecting that adds a lot of complexity for little gain.
370b57cec5SDimitry Andric ///
38*349cc55cSDimitry Andric /// Iterators are expected to have const rules analogous to pointers, with a
39*349cc55cSDimitry Andric /// single, const-qualified operator*() that returns ReferenceT. This matches
40*349cc55cSDimitry Andric /// the second and third pointers in the following example:
41*349cc55cSDimitry Andric /// \code
42*349cc55cSDimitry Andric ///   int Value;
43*349cc55cSDimitry Andric ///   { int *I = &Value; }             // ReferenceT 'int&'
44*349cc55cSDimitry Andric ///   { int *const I = &Value; }       // ReferenceT 'int&'; const
45*349cc55cSDimitry Andric ///   { const int *I = &Value; }       // ReferenceT 'const int&'
46*349cc55cSDimitry Andric ///   { const int *const I = &Value; } // ReferenceT 'const int&'; const
47*349cc55cSDimitry Andric /// \endcode
48*349cc55cSDimitry Andric /// If an iterator facade returns a handle to its own state, then T (and
49*349cc55cSDimitry Andric /// PointerT and ReferenceT) should usually be const-qualified. Otherwise, if
50*349cc55cSDimitry Andric /// clients are expected to modify the handle itself, the field can be declared
51*349cc55cSDimitry Andric /// mutable or use const_cast.
52*349cc55cSDimitry Andric ///
530b57cec5SDimitry Andric /// Classes wishing to use `iterator_facade_base` should implement the following
540b57cec5SDimitry Andric /// methods:
550b57cec5SDimitry Andric ///
560b57cec5SDimitry Andric /// Forward Iterators:
570b57cec5SDimitry Andric ///   (All of the following methods)
580b57cec5SDimitry Andric ///   - DerivedT &operator=(const DerivedT &R);
590b57cec5SDimitry Andric ///   - bool operator==(const DerivedT &R) const;
60*349cc55cSDimitry Andric ///   - T &operator*() const;
610b57cec5SDimitry Andric ///   - DerivedT &operator++();
620b57cec5SDimitry Andric ///
630b57cec5SDimitry Andric /// Bidirectional Iterators:
640b57cec5SDimitry Andric ///   (All methods of forward iterators, plus the following)
650b57cec5SDimitry Andric ///   - DerivedT &operator--();
660b57cec5SDimitry Andric ///
670b57cec5SDimitry Andric /// Random-access Iterators:
680b57cec5SDimitry Andric ///   (All methods of bidirectional iterators excluding the following)
690b57cec5SDimitry Andric ///   - DerivedT &operator++();
700b57cec5SDimitry Andric ///   - DerivedT &operator--();
710b57cec5SDimitry Andric ///   (and plus the following)
720b57cec5SDimitry Andric ///   - bool operator<(const DerivedT &RHS) const;
730b57cec5SDimitry Andric ///   - DifferenceTypeT operator-(const DerivedT &R) const;
740b57cec5SDimitry Andric ///   - DerivedT &operator+=(DifferenceTypeT N);
750b57cec5SDimitry Andric ///   - DerivedT &operator-=(DifferenceTypeT N);
760b57cec5SDimitry Andric ///
770b57cec5SDimitry Andric template <typename DerivedT, typename IteratorCategoryT, typename T,
780b57cec5SDimitry Andric           typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *,
790b57cec5SDimitry Andric           typename ReferenceT = T &>
80fe6060f1SDimitry Andric class iterator_facade_base {
81fe6060f1SDimitry Andric public:
82fe6060f1SDimitry Andric   using iterator_category = IteratorCategoryT;
83fe6060f1SDimitry Andric   using value_type = T;
84fe6060f1SDimitry Andric   using difference_type = DifferenceTypeT;
85fe6060f1SDimitry Andric   using pointer = PointerT;
86fe6060f1SDimitry Andric   using reference = ReferenceT;
87fe6060f1SDimitry Andric 
880b57cec5SDimitry Andric protected:
890b57cec5SDimitry Andric   enum {
900b57cec5SDimitry Andric     IsRandomAccess = std::is_base_of<std::random_access_iterator_tag,
910b57cec5SDimitry Andric                                      IteratorCategoryT>::value,
920b57cec5SDimitry Andric     IsBidirectional = std::is_base_of<std::bidirectional_iterator_tag,
930b57cec5SDimitry Andric                                       IteratorCategoryT>::value,
940b57cec5SDimitry Andric   };
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   /// A proxy object for computing a reference via indirecting a copy of an
970b57cec5SDimitry Andric   /// iterator. This is used in APIs which need to produce a reference via
980b57cec5SDimitry Andric   /// indirection but for which the iterator object might be a temporary. The
990b57cec5SDimitry Andric   /// proxy preserves the iterator internally and exposes the indirected
1000b57cec5SDimitry Andric   /// reference via a conversion operator.
1010b57cec5SDimitry Andric   class ReferenceProxy {
1020b57cec5SDimitry Andric     friend iterator_facade_base;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric     DerivedT I;
1050b57cec5SDimitry Andric 
ReferenceProxy(DerivedT I)1060b57cec5SDimitry Andric     ReferenceProxy(DerivedT I) : I(std::move(I)) {}
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   public:
ReferenceT()1090b57cec5SDimitry Andric     operator ReferenceT() const { return *I; }
1100b57cec5SDimitry Andric   };
1110b57cec5SDimitry Andric 
112*349cc55cSDimitry Andric   /// A proxy object for computing a pointer via indirecting a copy of a
113*349cc55cSDimitry Andric   /// reference. This is used in APIs which need to produce a pointer but for
114*349cc55cSDimitry Andric   /// which the reference might be a temporary. The proxy preserves the
115*349cc55cSDimitry Andric   /// reference internally and exposes the pointer via a arrow operator.
116*349cc55cSDimitry Andric   class PointerProxy {
117*349cc55cSDimitry Andric     friend iterator_facade_base;
118*349cc55cSDimitry Andric 
119*349cc55cSDimitry Andric     ReferenceT R;
120*349cc55cSDimitry Andric 
121*349cc55cSDimitry Andric     template <typename RefT>
PointerProxy(RefT && R)122*349cc55cSDimitry Andric     PointerProxy(RefT &&R) : R(std::forward<RefT>(R)) {}
123*349cc55cSDimitry Andric 
124*349cc55cSDimitry Andric   public:
125*349cc55cSDimitry Andric     PointerT operator->() const { return &R; }
126*349cc55cSDimitry Andric   };
127*349cc55cSDimitry Andric 
1280b57cec5SDimitry Andric public:
1290b57cec5SDimitry Andric   DerivedT operator+(DifferenceTypeT n) const {
1300b57cec5SDimitry Andric     static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
1310b57cec5SDimitry Andric                   "Must pass the derived type to this template!");
1320b57cec5SDimitry Andric     static_assert(
1330b57cec5SDimitry Andric         IsRandomAccess,
1340b57cec5SDimitry Andric         "The '+' operator is only defined for random access iterators.");
1350b57cec5SDimitry Andric     DerivedT tmp = *static_cast<const DerivedT *>(this);
1360b57cec5SDimitry Andric     tmp += n;
1370b57cec5SDimitry Andric     return tmp;
1380b57cec5SDimitry Andric   }
1390b57cec5SDimitry Andric   friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) {
1400b57cec5SDimitry Andric     static_assert(
1410b57cec5SDimitry Andric         IsRandomAccess,
1420b57cec5SDimitry Andric         "The '+' operator is only defined for random access iterators.");
1430b57cec5SDimitry Andric     return i + n;
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric   DerivedT operator-(DifferenceTypeT n) const {
1460b57cec5SDimitry Andric     static_assert(
1470b57cec5SDimitry Andric         IsRandomAccess,
1480b57cec5SDimitry Andric         "The '-' operator is only defined for random access iterators.");
1490b57cec5SDimitry Andric     DerivedT tmp = *static_cast<const DerivedT *>(this);
1500b57cec5SDimitry Andric     tmp -= n;
1510b57cec5SDimitry Andric     return tmp;
1520b57cec5SDimitry Andric   }
1530b57cec5SDimitry Andric 
1540b57cec5SDimitry Andric   DerivedT &operator++() {
1550b57cec5SDimitry Andric     static_assert(std::is_base_of<iterator_facade_base, DerivedT>::value,
1560b57cec5SDimitry Andric                   "Must pass the derived type to this template!");
1570b57cec5SDimitry Andric     return static_cast<DerivedT *>(this)->operator+=(1);
1580b57cec5SDimitry Andric   }
1590b57cec5SDimitry Andric   DerivedT operator++(int) {
1600b57cec5SDimitry Andric     DerivedT tmp = *static_cast<DerivedT *>(this);
1610b57cec5SDimitry Andric     ++*static_cast<DerivedT *>(this);
1620b57cec5SDimitry Andric     return tmp;
1630b57cec5SDimitry Andric   }
1640b57cec5SDimitry Andric   DerivedT &operator--() {
1650b57cec5SDimitry Andric     static_assert(
1660b57cec5SDimitry Andric         IsBidirectional,
1670b57cec5SDimitry Andric         "The decrement operator is only defined for bidirectional iterators.");
1680b57cec5SDimitry Andric     return static_cast<DerivedT *>(this)->operator-=(1);
1690b57cec5SDimitry Andric   }
1700b57cec5SDimitry Andric   DerivedT operator--(int) {
1710b57cec5SDimitry Andric     static_assert(
1720b57cec5SDimitry Andric         IsBidirectional,
1730b57cec5SDimitry Andric         "The decrement operator is only defined for bidirectional iterators.");
1740b57cec5SDimitry Andric     DerivedT tmp = *static_cast<DerivedT *>(this);
1750b57cec5SDimitry Andric     --*static_cast<DerivedT *>(this);
1760b57cec5SDimitry Andric     return tmp;
1770b57cec5SDimitry Andric   }
1780b57cec5SDimitry Andric 
179e8d8bef9SDimitry Andric #ifndef __cpp_impl_three_way_comparison
1800b57cec5SDimitry Andric   bool operator!=(const DerivedT &RHS) const {
181e8d8bef9SDimitry Andric     return !(static_cast<const DerivedT &>(*this) == RHS);
1820b57cec5SDimitry Andric   }
183e8d8bef9SDimitry Andric #endif
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   bool operator>(const DerivedT &RHS) const {
1860b57cec5SDimitry Andric     static_assert(
1870b57cec5SDimitry Andric         IsRandomAccess,
1880b57cec5SDimitry Andric         "Relational operators are only defined for random access iterators.");
189e8d8bef9SDimitry Andric     return !(static_cast<const DerivedT &>(*this) < RHS) &&
190e8d8bef9SDimitry Andric            !(static_cast<const DerivedT &>(*this) == RHS);
1910b57cec5SDimitry Andric   }
1920b57cec5SDimitry Andric   bool operator<=(const DerivedT &RHS) const {
1930b57cec5SDimitry Andric     static_assert(
1940b57cec5SDimitry Andric         IsRandomAccess,
1950b57cec5SDimitry Andric         "Relational operators are only defined for random access iterators.");
196e8d8bef9SDimitry Andric     return !(static_cast<const DerivedT &>(*this) > RHS);
1970b57cec5SDimitry Andric   }
1980b57cec5SDimitry Andric   bool operator>=(const DerivedT &RHS) const {
1990b57cec5SDimitry Andric     static_assert(
2000b57cec5SDimitry Andric         IsRandomAccess,
2010b57cec5SDimitry Andric         "Relational operators are only defined for random access iterators.");
202e8d8bef9SDimitry Andric     return !(static_cast<const DerivedT &>(*this) < RHS);
2030b57cec5SDimitry Andric   }
2040b57cec5SDimitry Andric 
205*349cc55cSDimitry Andric   PointerProxy operator->() const {
206*349cc55cSDimitry Andric     return static_cast<const DerivedT *>(this)->operator*();
2070b57cec5SDimitry Andric   }
2080b57cec5SDimitry Andric   ReferenceProxy operator[](DifferenceTypeT n) const {
2090b57cec5SDimitry Andric     static_assert(IsRandomAccess,
2100b57cec5SDimitry Andric                   "Subscripting is only defined for random access iterators.");
211*349cc55cSDimitry Andric     return static_cast<const DerivedT *>(this)->operator+(n);
2120b57cec5SDimitry Andric   }
2130b57cec5SDimitry Andric };
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric /// CRTP base class for adapting an iterator to a different type.
2160b57cec5SDimitry Andric ///
2170b57cec5SDimitry Andric /// This class can be used through CRTP to adapt one iterator into another.
2180b57cec5SDimitry Andric /// Typically this is done through providing in the derived class a custom \c
2190b57cec5SDimitry Andric /// operator* implementation. Other methods can be overridden as well.
2200b57cec5SDimitry Andric template <
2210b57cec5SDimitry Andric     typename DerivedT, typename WrappedIteratorT,
2220b57cec5SDimitry Andric     typename IteratorCategoryT =
2230b57cec5SDimitry Andric         typename std::iterator_traits<WrappedIteratorT>::iterator_category,
2240b57cec5SDimitry Andric     typename T = typename std::iterator_traits<WrappedIteratorT>::value_type,
2250b57cec5SDimitry Andric     typename DifferenceTypeT =
2260b57cec5SDimitry Andric         typename std::iterator_traits<WrappedIteratorT>::difference_type,
2275ffd83dbSDimitry Andric     typename PointerT = std::conditional_t<
2280b57cec5SDimitry Andric         std::is_same<T, typename std::iterator_traits<
2290b57cec5SDimitry Andric                             WrappedIteratorT>::value_type>::value,
2305ffd83dbSDimitry Andric         typename std::iterator_traits<WrappedIteratorT>::pointer, T *>,
2315ffd83dbSDimitry Andric     typename ReferenceT = std::conditional_t<
2320b57cec5SDimitry Andric         std::is_same<T, typename std::iterator_traits<
2330b57cec5SDimitry Andric                             WrappedIteratorT>::value_type>::value,
2345ffd83dbSDimitry Andric         typename std::iterator_traits<WrappedIteratorT>::reference, T &>>
2350b57cec5SDimitry Andric class iterator_adaptor_base
2360b57cec5SDimitry Andric     : public iterator_facade_base<DerivedT, IteratorCategoryT, T,
2370b57cec5SDimitry Andric                                   DifferenceTypeT, PointerT, ReferenceT> {
2380b57cec5SDimitry Andric   using BaseT = typename iterator_adaptor_base::iterator_facade_base;
2390b57cec5SDimitry Andric 
2400b57cec5SDimitry Andric protected:
2410b57cec5SDimitry Andric   WrappedIteratorT I;
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   iterator_adaptor_base() = default;
2440b57cec5SDimitry Andric 
iterator_adaptor_base(WrappedIteratorT u)2450b57cec5SDimitry Andric   explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {
2460b57cec5SDimitry Andric     static_assert(std::is_base_of<iterator_adaptor_base, DerivedT>::value,
2470b57cec5SDimitry Andric                   "Must pass the derived type to this template!");
2480b57cec5SDimitry Andric   }
2490b57cec5SDimitry Andric 
wrapped()2500b57cec5SDimitry Andric   const WrappedIteratorT &wrapped() const { return I; }
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric public:
2530b57cec5SDimitry Andric   using difference_type = DifferenceTypeT;
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric   DerivedT &operator+=(difference_type n) {
2560b57cec5SDimitry Andric     static_assert(
2570b57cec5SDimitry Andric         BaseT::IsRandomAccess,
2580b57cec5SDimitry Andric         "The '+=' operator is only defined for random access iterators.");
2590b57cec5SDimitry Andric     I += n;
2600b57cec5SDimitry Andric     return *static_cast<DerivedT *>(this);
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric   DerivedT &operator-=(difference_type n) {
2630b57cec5SDimitry Andric     static_assert(
2640b57cec5SDimitry Andric         BaseT::IsRandomAccess,
2650b57cec5SDimitry Andric         "The '-=' operator is only defined for random access iterators.");
2660b57cec5SDimitry Andric     I -= n;
2670b57cec5SDimitry Andric     return *static_cast<DerivedT *>(this);
2680b57cec5SDimitry Andric   }
2690b57cec5SDimitry Andric   using BaseT::operator-;
2700b57cec5SDimitry Andric   difference_type operator-(const DerivedT &RHS) const {
2710b57cec5SDimitry Andric     static_assert(
2720b57cec5SDimitry Andric         BaseT::IsRandomAccess,
2730b57cec5SDimitry Andric         "The '-' operator is only defined for random access iterators.");
2740b57cec5SDimitry Andric     return I - RHS.I;
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric   // We have to explicitly provide ++ and -- rather than letting the facade
2780b57cec5SDimitry Andric   // forward to += because WrappedIteratorT might not support +=.
2790b57cec5SDimitry Andric   using BaseT::operator++;
2800b57cec5SDimitry Andric   DerivedT &operator++() {
2810b57cec5SDimitry Andric     ++I;
2820b57cec5SDimitry Andric     return *static_cast<DerivedT *>(this);
2830b57cec5SDimitry Andric   }
2840b57cec5SDimitry Andric   using BaseT::operator--;
2850b57cec5SDimitry Andric   DerivedT &operator--() {
2860b57cec5SDimitry Andric     static_assert(
2870b57cec5SDimitry Andric         BaseT::IsBidirectional,
2880b57cec5SDimitry Andric         "The decrement operator is only defined for bidirectional iterators.");
2890b57cec5SDimitry Andric     --I;
2900b57cec5SDimitry Andric     return *static_cast<DerivedT *>(this);
2910b57cec5SDimitry Andric   }
2920b57cec5SDimitry Andric 
293e8d8bef9SDimitry Andric   friend bool operator==(const iterator_adaptor_base &LHS,
294e8d8bef9SDimitry Andric                          const iterator_adaptor_base &RHS) {
295e8d8bef9SDimitry Andric     return LHS.I == RHS.I;
296e8d8bef9SDimitry Andric   }
297e8d8bef9SDimitry Andric   friend bool operator<(const iterator_adaptor_base &LHS,
298e8d8bef9SDimitry Andric                         const iterator_adaptor_base &RHS) {
2990b57cec5SDimitry Andric     static_assert(
3000b57cec5SDimitry Andric         BaseT::IsRandomAccess,
3010b57cec5SDimitry Andric         "Relational operators are only defined for random access iterators.");
302e8d8bef9SDimitry Andric     return LHS.I < RHS.I;
3030b57cec5SDimitry Andric   }
3040b57cec5SDimitry Andric 
3050b57cec5SDimitry Andric   ReferenceT operator*() const { return *I; }
3060b57cec5SDimitry Andric };
3070b57cec5SDimitry Andric 
3080b57cec5SDimitry Andric /// An iterator type that allows iterating over the pointees via some
3090b57cec5SDimitry Andric /// other iterator.
3100b57cec5SDimitry Andric ///
3110b57cec5SDimitry Andric /// The typical usage of this is to expose a type that iterates over Ts, but
3120b57cec5SDimitry Andric /// which is implemented with some iterator over T*s:
3130b57cec5SDimitry Andric ///
3140b57cec5SDimitry Andric /// \code
3150b57cec5SDimitry Andric ///   using iterator = pointee_iterator<SmallVectorImpl<T *>::iterator>;
3160b57cec5SDimitry Andric /// \endcode
3170b57cec5SDimitry Andric template <typename WrappedIteratorT,
3185ffd83dbSDimitry Andric           typename T = std::remove_reference_t<decltype(
3195ffd83dbSDimitry Andric               **std::declval<WrappedIteratorT>())>>
3200b57cec5SDimitry Andric struct pointee_iterator
3210b57cec5SDimitry Andric     : iterator_adaptor_base<
3220b57cec5SDimitry Andric           pointee_iterator<WrappedIteratorT, T>, WrappedIteratorT,
3230b57cec5SDimitry Andric           typename std::iterator_traits<WrappedIteratorT>::iterator_category,
3240b57cec5SDimitry Andric           T> {
3250b57cec5SDimitry Andric   pointee_iterator() = default;
3260b57cec5SDimitry Andric   template <typename U>
pointee_iteratorpointee_iterator3270b57cec5SDimitry Andric   pointee_iterator(U &&u)
3280b57cec5SDimitry Andric       : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {}
3290b57cec5SDimitry Andric 
3300b57cec5SDimitry Andric   T &operator*() const { return **this->I; }
3310b57cec5SDimitry Andric };
3320b57cec5SDimitry Andric 
3330b57cec5SDimitry Andric template <typename RangeT, typename WrappedIteratorT =
3340b57cec5SDimitry Andric                                decltype(std::begin(std::declval<RangeT>()))>
3350b57cec5SDimitry Andric iterator_range<pointee_iterator<WrappedIteratorT>>
make_pointee_range(RangeT && Range)3360b57cec5SDimitry Andric make_pointee_range(RangeT &&Range) {
3370b57cec5SDimitry Andric   using PointeeIteratorT = pointee_iterator<WrappedIteratorT>;
3380b57cec5SDimitry Andric   return make_range(PointeeIteratorT(std::begin(std::forward<RangeT>(Range))),
3390b57cec5SDimitry Andric                     PointeeIteratorT(std::end(std::forward<RangeT>(Range))));
3400b57cec5SDimitry Andric }
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric template <typename WrappedIteratorT,
3430b57cec5SDimitry Andric           typename T = decltype(&*std::declval<WrappedIteratorT>())>
3440b57cec5SDimitry Andric class pointer_iterator
3450b57cec5SDimitry Andric     : public iterator_adaptor_base<
3460b57cec5SDimitry Andric           pointer_iterator<WrappedIteratorT, T>, WrappedIteratorT,
3470b57cec5SDimitry Andric           typename std::iterator_traits<WrappedIteratorT>::iterator_category,
3480b57cec5SDimitry Andric           T> {
3490b57cec5SDimitry Andric   mutable T Ptr;
3500b57cec5SDimitry Andric 
3510b57cec5SDimitry Andric public:
3520b57cec5SDimitry Andric   pointer_iterator() = default;
3530b57cec5SDimitry Andric 
pointer_iterator(WrappedIteratorT u)3540b57cec5SDimitry Andric   explicit pointer_iterator(WrappedIteratorT u)
3550b57cec5SDimitry Andric       : pointer_iterator::iterator_adaptor_base(std::move(u)) {}
3560b57cec5SDimitry Andric 
357*349cc55cSDimitry Andric   T &operator*() const { return Ptr = &*this->I; }
3580b57cec5SDimitry Andric };
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric template <typename RangeT, typename WrappedIteratorT =
3610b57cec5SDimitry Andric                                decltype(std::begin(std::declval<RangeT>()))>
3620b57cec5SDimitry Andric iterator_range<pointer_iterator<WrappedIteratorT>>
make_pointer_range(RangeT && Range)3630b57cec5SDimitry Andric make_pointer_range(RangeT &&Range) {
3640b57cec5SDimitry Andric   using PointerIteratorT = pointer_iterator<WrappedIteratorT>;
3650b57cec5SDimitry Andric   return make_range(PointerIteratorT(std::begin(std::forward<RangeT>(Range))),
3660b57cec5SDimitry Andric                     PointerIteratorT(std::end(std::forward<RangeT>(Range))));
3670b57cec5SDimitry Andric }
3680b57cec5SDimitry Andric 
369480093f4SDimitry Andric template <typename WrappedIteratorT,
3705ffd83dbSDimitry Andric           typename T1 = std::remove_reference_t<decltype(
3715ffd83dbSDimitry Andric               **std::declval<WrappedIteratorT>())>,
3725ffd83dbSDimitry Andric           typename T2 = std::add_pointer_t<T1>>
3735ffd83dbSDimitry Andric using raw_pointer_iterator =
3745ffd83dbSDimitry Andric     pointer_iterator<pointee_iterator<WrappedIteratorT, T1>, T2>;
375480093f4SDimitry Andric 
3760b57cec5SDimitry Andric } // end namespace llvm
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric #endif // LLVM_ADT_ITERATOR_H
379