#ifndef SPROUT_ITERATOR_COUNTING_ITERATOR_HPP #define SPROUT_ITERATOR_COUNTING_ITERATOR_HPP #include #include #include #include #include #include #include #include namespace sprout { // // counting_iterator // template class counting_iterator : public std::iterator< std::random_access_iterator_tag, Incrementable, std::ptrdiff_t, Incrementable*, Incrementable > { public: typedef std::random_access_iterator_tag iterator_category; typedef Incrementable value_type; typedef std::ptrdiff_t difference_type; typedef value_type* pointer; typedef value_type reference; private: value_type current_; private: public: SPROUT_CONSTEXPR counting_iterator() : current_(std::numeric_limits::max()) {} counting_iterator(counting_iterator const&) = default; explicit SPROUT_CONSTEXPR counting_iterator(value_type const& v) : current_(v) {} template SPROUT_CONSTEXPR counting_iterator(counting_iterator const& it) : current_(it.current_) {} template counting_iterator& operator=(counting_iterator const& it) { counting_iterator temp(it); temp.swap(*this); return *this; } SPROUT_CONSTEXPR reference operator*() const { return current_; } SPROUT_CONSTEXPR pointer operator->() const { return ¤t_; } counting_iterator& operator++() { ++current_; return *this; } counting_iterator operator++(int) { counting_iterator result(*this); ++current_; return result; } counting_iterator& operator--() { --current_; return *this; } counting_iterator operator--(int) { counting_iterator temp(*this); --current_; return temp; } SPROUT_CONSTEXPR counting_iterator operator+(difference_type n) const { return counting_iterator(current_ + n); } SPROUT_CONSTEXPR counting_iterator operator-(difference_type n) const { return counting_iterator(current_ - n); } counting_iterator& operator+=(difference_type n) { counting_iterator temp(current_ + n); temp.swap(*this); return *this; } counting_iterator& operator-=(difference_type n) { counting_iterator temp(current_ - n); temp.swap(*this); return *this; } SPROUT_CONSTEXPR reference operator[](difference_type n) const { return current_ + n; } SPROUT_CONSTEXPR counting_iterator next() const { return counting_iterator(current_ + 1); } SPROUT_CONSTEXPR counting_iterator prev() const { return counting_iterator(current_ - 1); } void swap(counting_iterator& other) { using std::swap; swap(current_, other.current_); } }; template SPROUT_CONSTEXPR bool operator==( sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs ) { return *lhs == *rhs; } template SPROUT_CONSTEXPR bool operator!=( sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs ) { return !(lhs == rhs); } template SPROUT_CONSTEXPR bool operator<( sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs ) { return *lhs < *rhs; } template SPROUT_CONSTEXPR bool operator>( sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs ) { return rhs < lhs; } template SPROUT_CONSTEXPR bool operator<=( sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs ) { return !(rhs < lhs); } template SPROUT_CONSTEXPR bool operator>=( sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs ) { return !(lhs < rhs); } template SPROUT_CONSTEXPR typename sprout::counting_iterator::difference_type operator-( sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs ) { return static_cast::difference_type>(*lhs - *rhs); } template SPROUT_CONSTEXPR sprout::counting_iterator operator+( typename sprout::counting_iterator::difference_type n, sprout::counting_iterator const& it ) { return it + n; } // // make_counting_iterator // template SPROUT_CONSTEXPR sprout::counting_iterator make_counting_iterator(Incrementable const& v) { return sprout::counting_iterator(v); } // // swap // template inline void swap(sprout::counting_iterator& lhs, sprout::counting_iterator& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } // // distance // template inline SPROUT_CONSTEXPR typename std::iterator_traits >::difference_type distance( sprout::counting_iterator first, sprout::counting_iterator last ) { return last - first; } // // iterator_next // template inline SPROUT_CONSTEXPR sprout::counting_iterator iterator_next( sprout::counting_iterator const& it ) { return it.next(); } template inline SPROUT_CONSTEXPR sprout::counting_iterator iterator_next( sprout::counting_iterator const& it, typename sprout::counting_iterator::difference_type n ) { return it + n; } // // iterator_prev // template inline SPROUT_CONSTEXPR sprout::counting_iterator iterator_prev( sprout::counting_iterator const& it ) { return it.prev(); } template inline SPROUT_CONSTEXPR sprout::counting_iterator iterator_prev( sprout::counting_iterator const& it, typename sprout::counting_iterator::difference_type n ) { return it - n; } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_COUNTING_ITERATOR_HPP