//===----------------------------------------------------------------------===// // // The LLVM Compiler Infrastructure // // This file is dual licensed under the MIT and the University of Illinois Open // Source Licenses. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef ITERATORS_H #define ITERATORS_H #include <iterator> #include <stdexcept> #include <cstddef> #include <cassert> #include "test_macros.h" #if TEST_STD_VER >= 11 #define DELETE_FUNCTION = delete #else #define DELETE_FUNCTION #endif template <class It> class output_iterator { It it_; template <class U> friend class output_iterator; public: typedef std::output_iterator_tag iterator_category; typedef void value_type; typedef typename std::iterator_traits<It>::difference_type difference_type; typedef It pointer; typedef typename std::iterator_traits<It>::reference reference; It base() const {return it_;} output_iterator () {} explicit output_iterator(It it) : it_(it) {} template <class U> output_iterator(const output_iterator<U>& u) :it_(u.it_) {} reference operator*() const {return *it_;} output_iterator& operator++() {++it_; return *this;} output_iterator operator++(int) {output_iterator tmp(*this); ++(*this); return tmp;} template <class T> void operator,(T const &) DELETE_FUNCTION; }; template <class It, class ItTraits = It> class input_iterator { typedef std::iterator_traits<ItTraits> Traits; It it_; template <class U, class T> friend class input_iterator; public: typedef std::input_iterator_tag iterator_category; typedef typename Traits::value_type value_type; typedef typename Traits::difference_type difference_type; typedef It pointer; typedef typename Traits::reference reference; It base() const {return it_;} input_iterator() : it_() {} explicit input_iterator(It it) : it_(it) {} template <class U, class T> input_iterator(const input_iterator<U, T>& u) :it_(u.it_) {} reference operator*() const {return *it_;} pointer operator->() const {return it_;} input_iterator& operator++() {++it_; return *this;} input_iterator operator++(int) {input_iterator tmp(*this); ++(*this); return tmp;} friend bool operator==(const input_iterator& x, const input_iterator& y) {return x.it_ == y.it_;} friend bool operator!=(const input_iterator& x, const input_iterator& y) {return !(x == y);} template <class T> void operator,(T const &) DELETE_FUNCTION; }; template <class T, class TV, class U, class UV> inline bool operator==(const input_iterator<T, TV>& x, const input_iterator<U, UV>& y) { return x.base() == y.base(); } template <class T, class TV, class U, class UV> inline bool operator!=(const input_iterator<T, TV>& x, const input_iterator<U, UV>& y) { return !(x == y); } template <class It> class forward_iterator { It it_; template <class U> friend class forward_iterator; public: typedef std::forward_iterator_tag iterator_category; typedef typename std::iterator_traits<It>::value_type value_type; typedef typename std::iterator_traits<It>::difference_type difference_type; typedef It pointer; typedef typename std::iterator_traits<It>::reference reference; It base() const {return it_;} forward_iterator() : it_() {} explicit forward_iterator(It it) : it_(it) {} template <class U> forward_iterator(const forward_iterator<U>& u) :it_(u.it_) {} reference operator*() const {return *it_;} pointer operator->() const {return it_;} forward_iterator& operator++() {++it_; return *this;} forward_iterator operator++(int) {forward_iterator tmp(*this); ++(*this); return tmp;} friend bool operator==(const forward_iterator& x, const forward_iterator& y) {return x.it_ == y.it_;} friend bool operator!=(const forward_iterator& x, const forward_iterator& y) {return !(x == y);} template <class T> void operator,(T const &) DELETE_FUNCTION; }; template <class T, class U> inline bool operator==(const forward_iterator<T>& x, const forward_iterator<U>& y) { return x.base() == y.base(); } template <class T, class U> inline bool operator!=(const forward_iterator<T>& x, const forward_iterator<U>& y) { return !(x == y); } template <class It> class bidirectional_iterator { It it_; template <class U> friend class bidirectional_iterator; public: typedef std::bidirectional_iterator_tag iterator_category; typedef typename std::iterator_traits<It>::value_type value_type; typedef typename std::iterator_traits<It>::difference_type difference_type; typedef It pointer; typedef typename std::iterator_traits<It>::reference reference; It base() const {return it_;} bidirectional_iterator() : it_() {} explicit bidirectional_iterator(It it) : it_(it) {} template <class U> bidirectional_iterator(const bidirectional_iterator<U>& u) :it_(u.it_) {} reference operator*() const {return *it_;} pointer operator->() const {return it_;} bidirectional_iterator& operator++() {++it_; return *this;} bidirectional_iterator operator++(int) {bidirectional_iterator tmp(*this); ++(*this); return tmp;} bidirectional_iterator& operator--() {--it_; return *this;} bidirectional_iterator operator--(int) {bidirectional_iterator tmp(*this); --(*this); return tmp;} template <class T> void operator,(T const &) DELETE_FUNCTION; }; template <class T, class U> inline bool operator==(const bidirectional_iterator<T>& x, const bidirectional_iterator<U>& y) { return x.base() == y.base(); } template <class T, class U> inline bool operator!=(const bidirectional_iterator<T>& x, const bidirectional_iterator<U>& y) { return !(x == y); } template <class It> class random_access_iterator { It it_; template <class U> friend class random_access_iterator; public: typedef std::random_access_iterator_tag iterator_category; typedef typename std::iterator_traits<It>::value_type value_type; typedef typename std::iterator_traits<It>::difference_type difference_type; typedef It pointer; typedef typename std::iterator_traits<It>::reference reference; It base() const {return it_;} random_access_iterator() : it_() {} explicit random_access_iterator(It it) : it_(it) {} template <class U> random_access_iterator(const random_access_iterator<U>& u) :it_(u.it_) {} reference operator*() const {return *it_;} pointer operator->() const {return it_;} random_access_iterator& operator++() {++it_; return *this;} random_access_iterator operator++(int) {random_access_iterator tmp(*this); ++(*this); return tmp;} random_access_iterator& operator--() {--it_; return *this;} random_access_iterator operator--(int) {random_access_iterator tmp(*this); --(*this); return tmp;} random_access_iterator& operator+=(difference_type n) {it_ += n; return *this;} random_access_iterator operator+(difference_type n) const {random_access_iterator tmp(*this); tmp += n; return tmp;} friend random_access_iterator operator+(difference_type n, random_access_iterator x) {x += n; return x;} random_access_iterator& operator-=(difference_type n) {return *this += -n;} random_access_iterator operator-(difference_type n) const {random_access_iterator tmp(*this); tmp -= n; return tmp;} reference operator[](difference_type n) const {return it_[n];} template <class T> void operator,(T const &) DELETE_FUNCTION; }; template <class T, class U> inline bool operator==(const random_access_iterator<T>& x, const random_access_iterator<U>& y) { return x.base() == y.base(); } template <class T, class U> inline bool operator!=(const random_access_iterator<T>& x, const random_access_iterator<U>& y) { return !(x == y); } template <class T, class U> inline bool operator<(const random_access_iterator<T>& x, const random_access_iterator<U>& y) { return x.base() < y.base(); } template <class T, class U> inline bool operator<=(const random_access_iterator<T>& x, const random_access_iterator<U>& y) { return !(y < x); } template <class T, class U> inline bool operator>(const random_access_iterator<T>& x, const random_access_iterator<U>& y) { return y < x; } template <class T, class U> inline bool operator>=(const random_access_iterator<T>& x, const random_access_iterator<U>& y) { return !(x < y); } template <class T, class U> inline typename std::iterator_traits<T>::difference_type operator-(const random_access_iterator<T>& x, const random_access_iterator<U>& y) { return x.base() - y.base(); } template <class Iter> inline Iter base(output_iterator<Iter> i) { return i.base(); } template <class Iter> inline Iter base(input_iterator<Iter> i) { return i.base(); } template <class Iter> inline Iter base(forward_iterator<Iter> i) { return i.base(); } template <class Iter> inline Iter base(bidirectional_iterator<Iter> i) { return i.base(); } template <class Iter> inline Iter base(random_access_iterator<Iter> i) { return i.base(); } template <class Iter> // everything else inline Iter base(Iter i) { return i; } template <typename T> struct ThrowingIterator { typedef std::bidirectional_iterator_tag iterator_category; typedef ptrdiff_t difference_type; typedef const T value_type; typedef const T * pointer; typedef const T & reference; enum ThrowingAction { TAIncrement, TADecrement, TADereference, TAAssignment, TAComparison }; // Constructors ThrowingIterator () : begin_(nullptr), end_(nullptr), current_(nullptr), action_(TADereference), index_(0) {} ThrowingIterator (const T *first, const T *last, size_t index = 0, ThrowingAction action = TADereference) : begin_(first), end_(last), current_(first), action_(action), index_(index) {} ThrowingIterator (const ThrowingIterator &rhs) : begin_(rhs.begin_), end_(rhs.end_), current_(rhs.current_), action_(rhs.action_), index_(rhs.index_) {} ThrowingIterator & operator= (const ThrowingIterator &rhs) { if (action_ == TAAssignment) { if (index_ == 0) #ifndef TEST_HAS_NO_EXCEPTIONS throw std::runtime_error ("throw from iterator assignment"); #else assert(false); #endif else --index_; } begin_ = rhs.begin_; end_ = rhs.end_; current_ = rhs.current_; action_ = rhs.action_; index_ = rhs.index_; return *this; } // iterator operations reference operator*() const { if (action_ == TADereference) { if (index_ == 0) #ifndef TEST_HAS_NO_EXCEPTIONS throw std::runtime_error ("throw from iterator dereference"); #else assert(false); #endif else --index_; } return *current_; } ThrowingIterator & operator++() { if (action_ == TAIncrement) { if (index_ == 0) #ifndef TEST_HAS_NO_EXCEPTIONS throw std::runtime_error ("throw from iterator increment"); #else assert(false); #endif else --index_; } ++current_; return *this; } ThrowingIterator operator++(int) { ThrowingIterator temp = *this; ++(*this); return temp; } ThrowingIterator & operator--() { if (action_ == TADecrement) { if (index_ == 0) #ifndef TEST_HAS_NO_EXCEPTIONS throw std::runtime_error ("throw from iterator decrement"); #else assert(false); #endif else --index_; } --current_; return *this; } ThrowingIterator operator--(int) { ThrowingIterator temp = *this; --(*this); return temp; } bool operator== (const ThrowingIterator &rhs) const { if (action_ == TAComparison) { if (index_ == 0) #ifndef TEST_HAS_NO_EXCEPTIONS throw std::runtime_error ("throw from iterator comparison"); #else assert(false); #endif else --index_; } bool atEndL = current_ == end_; bool atEndR = rhs.current_ == rhs.end_; if (atEndL != atEndR) return false; // one is at the end (or empty), the other is not. if (atEndL) return true; // both are at the end (or empty) return current_ == rhs.current_; } private: const T* begin_; const T* end_; const T* current_; ThrowingAction action_; mutable size_t index_; }; template <typename T> bool operator== (const ThrowingIterator<T>& a, const ThrowingIterator<T>& b) { return a.operator==(b); } template <typename T> bool operator!= (const ThrowingIterator<T>& a, const ThrowingIterator<T>& b) { return !a.operator==(b); } template <typename T> struct NonThrowingIterator { typedef std::bidirectional_iterator_tag iterator_category; typedef ptrdiff_t difference_type; typedef const T value_type; typedef const T * pointer; typedef const T & reference; // Constructors NonThrowingIterator () : begin_(nullptr), end_(nullptr), current_(nullptr) {} NonThrowingIterator (const T *first, const T* last) : begin_(first), end_(last), current_(first) {} NonThrowingIterator (const NonThrowingIterator &rhs) : begin_(rhs.begin_), end_(rhs.end_), current_(rhs.current_) {} NonThrowingIterator & operator= (const NonThrowingIterator &rhs) TEST_NOEXCEPT { begin_ = rhs.begin_; end_ = rhs.end_; current_ = rhs.current_; return *this; } // iterator operations reference operator*() const TEST_NOEXCEPT { return *current_; } NonThrowingIterator & operator++() TEST_NOEXCEPT { ++current_; return *this; } NonThrowingIterator operator++(int) TEST_NOEXCEPT { NonThrowingIterator temp = *this; ++(*this); return temp; } NonThrowingIterator & operator--() TEST_NOEXCEPT { --current_; return *this; } NonThrowingIterator operator--(int) TEST_NOEXCEPT { NonThrowingIterator temp = *this; --(*this); return temp; } bool operator== (const NonThrowingIterator &rhs) const TEST_NOEXCEPT { bool atEndL = current_ == end_; bool atEndR = rhs.current_ == rhs.end_; if (atEndL != atEndR) return false; // one is at the end (or empty), the other is not. if (atEndL) return true; // both are at the end (or empty) return current_ == rhs.current_; } private: const T* begin_; const T* end_; const T* current_; }; template <typename T> bool operator== (const NonThrowingIterator<T>& a, const NonThrowingIterator<T>& b) TEST_NOEXCEPT { return a.operator==(b); } template <typename T> bool operator!= (const NonThrowingIterator<T>& a, const NonThrowingIterator<T>& b) TEST_NOEXCEPT { return !a.operator==(b); } #undef DELETE_FUNCTION #endif // ITERATORS_H