| //===- iterator.h - Utilities for using and defining iterators --*- C++ -*-===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #ifndef LLVM_ADT_ITERATOR_H | |
| #define LLVM_ADT_ITERATOR_H | |
| #include <cstddef> | |
| #include <iterator> | |
| #include <type_traits> | |
| namespace llvm { | |
| /// \brief CRTP base class which implements the entire standard iterator facade | |
| /// in terms of a minimal subset of the interface. | |
| /// | |
| /// Use this when it is reasonable to implement most of the iterator | |
| /// functionality in terms of a core subset. If you need special behavior or | |
| /// there are performance implications for this, you may want to override the | |
| /// relevant members instead. | |
| /// | |
| /// Note, one abstraction that this does *not* provide is implementing | |
| /// subtraction in terms of addition by negating the difference. Negation isn't | |
| /// always information preserving, and I can see very reasonable iterator | |
| /// designs where this doesn't work well. It doesn't really force much added | |
| /// boilerplate anyways. | |
| /// | |
| /// Another abstraction that this doesn't provide is implementing increment in | |
| /// terms of addition of one. These aren't equivalent for all iterator | |
| /// categories, and respecting that adds a lot of complexity for little gain. | |
| template <typename DerivedT, typename IteratorCategoryT, typename T, | |
| typename DifferenceTypeT = std::ptrdiff_t, typename PointerT = T *, | |
| typename ReferenceT = T &> | |
| class iterator_facade_base | |
| : public std::iterator<IteratorCategoryT, T, DifferenceTypeT, PointerT, | |
| ReferenceT> { | |
| protected: | |
| enum { | |
| IsRandomAccess = | |
| std::is_base_of<std::random_access_iterator_tag, IteratorCategoryT>::value, | |
| IsBidirectional = | |
| std::is_base_of<std::bidirectional_iterator_tag, IteratorCategoryT>::value, | |
| }; | |
| /// A proxy object for computing a reference via indirecting a copy of an | |
| /// iterator. This is used in APIs which need to produce a reference via | |
| /// indirection but for which the iterator object might be a temporary. The | |
| /// proxy preserves the iterator internally and exposes the indirected | |
| /// reference via a conversion operator. | |
| class ReferenceProxy { | |
| friend iterator_facade_base; | |
| DerivedT I; | |
| ReferenceProxy(DerivedT I) : I(std::move(I)) {} | |
| public: | |
| operator ReferenceT() const { return *I; } | |
| }; | |
| public: | |
| DerivedT operator+(DifferenceTypeT n) const { | |
| static_assert( | |
| IsRandomAccess, | |
| "The '+' operator is only defined for random access iterators."); | |
| DerivedT tmp = *static_cast<const DerivedT *>(this); | |
| tmp += n; | |
| return tmp; | |
| } | |
| friend DerivedT operator+(DifferenceTypeT n, const DerivedT &i) { | |
| static_assert( | |
| IsRandomAccess, | |
| "The '+' operator is only defined for random access iterators."); | |
| return i + n; | |
| } | |
| DerivedT operator-(DifferenceTypeT n) const { | |
| static_assert( | |
| IsRandomAccess, | |
| "The '-' operator is only defined for random access iterators."); | |
| DerivedT tmp = *static_cast<const DerivedT *>(this); | |
| tmp -= n; | |
| return tmp; | |
| } | |
| DerivedT &operator++() { | |
| return static_cast<DerivedT *>(this)->operator+=(1); | |
| } | |
| DerivedT operator++(int) { | |
| DerivedT tmp = *static_cast<DerivedT *>(this); | |
| ++*static_cast<DerivedT *>(this); | |
| return tmp; | |
| } | |
| DerivedT &operator--() { | |
| static_assert( | |
| IsBidirectional, | |
| "The decrement operator is only defined for bidirectional iterators."); | |
| return static_cast<DerivedT *>(this)->operator-=(1); | |
| } | |
| DerivedT operator--(int) { | |
| static_assert( | |
| IsBidirectional, | |
| "The decrement operator is only defined for bidirectional iterators."); | |
| DerivedT tmp = *static_cast<DerivedT *>(this); | |
| --*static_cast<DerivedT *>(this); | |
| return tmp; | |
| } | |
| bool operator!=(const DerivedT &RHS) const { | |
| return !static_cast<const DerivedT *>(this)->operator==(RHS); | |
| } | |
| bool operator>(const DerivedT &RHS) const { | |
| static_assert( | |
| IsRandomAccess, | |
| "Relational operators are only defined for random access iterators."); | |
| return !static_cast<const DerivedT *>(this)->operator<(RHS) && | |
| !static_cast<const DerivedT *>(this)->operator==(RHS); | |
| } | |
| bool operator<=(const DerivedT &RHS) const { | |
| static_assert( | |
| IsRandomAccess, | |
| "Relational operators are only defined for random access iterators."); | |
| return !static_cast<const DerivedT *>(this)->operator>(RHS); | |
| } | |
| bool operator>=(const DerivedT &RHS) const { | |
| static_assert( | |
| IsRandomAccess, | |
| "Relational operators are only defined for random access iterators."); | |
| return !static_cast<const DerivedT *>(this)->operator<(RHS); | |
| } | |
| PointerT operator->() const { | |
| return &static_cast<const DerivedT *>(this)->operator*(); | |
| } | |
| ReferenceProxy operator[](DifferenceTypeT n) const { | |
| static_assert(IsRandomAccess, | |
| "Subscripting is only defined for random access iterators."); | |
| return ReferenceProxy(static_cast<const DerivedT *>(this)->operator+(n)); | |
| } | |
| }; | |
| /// \brief CRTP base class for adapting an iterator to a different type. | |
| /// | |
| /// This class can be used through CRTP to adapt one iterator into another. | |
| /// Typically this is done through providing in the derived class a custom \c | |
| /// operator* implementation. Other methods can be overridden as well. | |
| template < | |
| typename DerivedT, typename WrappedIteratorT, | |
| typename IteratorCategoryT = | |
| typename std::iterator_traits<WrappedIteratorT>::iterator_category, | |
| typename T = typename std::iterator_traits<WrappedIteratorT>::value_type, | |
| typename DifferenceTypeT = | |
| typename std::iterator_traits<WrappedIteratorT>::difference_type, | |
| typename PointerT = typename std::conditional< | |
| std::is_same<T, typename std::iterator_traits< | |
| WrappedIteratorT>::value_type>::value, | |
| typename std::iterator_traits<WrappedIteratorT>::pointer, T *>::type, | |
| typename ReferenceT = typename std::conditional< | |
| std::is_same<T, typename std::iterator_traits< | |
| WrappedIteratorT>::value_type>::value, | |
| typename std::iterator_traits<WrappedIteratorT>::reference, T &>::type, | |
| // Don't provide these, they are mostly to act as aliases below. | |
| typename WrappedTraitsT = std::iterator_traits<WrappedIteratorT>> | |
| class iterator_adaptor_base | |
| : public iterator_facade_base<DerivedT, IteratorCategoryT, T, | |
| DifferenceTypeT, PointerT, ReferenceT> { | |
| typedef typename iterator_adaptor_base::iterator_facade_base BaseT; | |
| protected: | |
| WrappedIteratorT I; | |
| iterator_adaptor_base() = default; | |
| explicit iterator_adaptor_base(WrappedIteratorT u) : I(std::move(u)) {} | |
| const WrappedIteratorT &wrapped() const { return I; } | |
| public: | |
| typedef DifferenceTypeT difference_type; | |
| DerivedT &operator+=(difference_type n) { | |
| static_assert( | |
| BaseT::IsRandomAccess, | |
| "The '+=' operator is only defined for random access iterators."); | |
| I += n; | |
| return *static_cast<DerivedT *>(this); | |
| } | |
| DerivedT &operator-=(difference_type n) { | |
| static_assert( | |
| BaseT::IsRandomAccess, | |
| "The '-=' operator is only defined for random access iterators."); | |
| I -= n; | |
| return *static_cast<DerivedT *>(this); | |
| } | |
| using BaseT::operator-; | |
| difference_type operator-(const DerivedT &RHS) const { | |
| static_assert( | |
| BaseT::IsRandomAccess, | |
| "The '-' operator is only defined for random access iterators."); | |
| return I - RHS.I; | |
| } | |
| // We have to explicitly provide ++ and -- rather than letting the facade | |
| // forward to += because WrappedIteratorT might not support +=. | |
| using BaseT::operator++; | |
| DerivedT &operator++() { | |
| ++I; | |
| return *static_cast<DerivedT *>(this); | |
| } | |
| using BaseT::operator--; | |
| DerivedT &operator--() { | |
| static_assert( | |
| BaseT::IsBidirectional, | |
| "The decrement operator is only defined for bidirectional iterators."); | |
| --I; | |
| return *static_cast<DerivedT *>(this); | |
| } | |
| bool operator==(const DerivedT &RHS) const { return I == RHS.I; } | |
| bool operator<(const DerivedT &RHS) const { | |
| static_assert( | |
| BaseT::IsRandomAccess, | |
| "Relational operators are only defined for random access iterators."); | |
| return I < RHS.I; | |
| } | |
| ReferenceT operator*() const { return *I; } | |
| }; | |
| /// \brief An iterator type that allows iterating over the pointees via some | |
| /// other iterator. | |
| /// | |
| /// The typical usage of this is to expose a type that iterates over Ts, but | |
| /// which is implemented with some iterator over T*s: | |
| /// | |
| /// \code | |
| /// typedef pointee_iterator<SmallVectorImpl<T *>::iterator> iterator; | |
| /// \endcode | |
| template <typename WrappedIteratorT, | |
| typename T = typename std::remove_reference< | |
| decltype(**std::declval<WrappedIteratorT>())>::type> | |
| struct pointee_iterator | |
| : iterator_adaptor_base< | |
| pointee_iterator<WrappedIteratorT>, WrappedIteratorT, | |
| typename std::iterator_traits<WrappedIteratorT>::iterator_category, | |
| T> { | |
| pointee_iterator() = default; | |
| template <typename U> | |
| pointee_iterator(U &&u) | |
| : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {} | |
| T &operator*() const { return **this->I; } | |
| }; | |
| template <typename WrappedIteratorT, | |
| typename T = decltype(&*std::declval<WrappedIteratorT>())> | |
| class pointer_iterator | |
| : public iterator_adaptor_base<pointer_iterator<WrappedIteratorT>, | |
| WrappedIteratorT, T> { | |
| mutable T Ptr; | |
| public: | |
| pointer_iterator() = default; | |
| explicit pointer_iterator(WrappedIteratorT u) | |
| : pointer_iterator::iterator_adaptor_base(std::move(u)) {} | |
| T &operator*() { return Ptr = &*this->I; } | |
| const T &operator*() const { return Ptr = &*this->I; } | |
| }; | |
| } // end namespace llvm | |
| #endif // LLVM_ADT_ITERATOR_H |