/*============================================================================= Copyright (c) 2011-2015 Bolero MURAKAMI https://github.com/bolero-MURAKAMI/Sprout Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) =============================================================================*/ #ifndef SPROUT_ITERATOR_COUNTING_ITERATOR_HPP #define SPROUT_ITERATOR_COUNTING_ITERATOR_HPP #include #include #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: template::value>::type = sprout::enabler> static SPROUT_CONSTEXPR T default_value() { return sprout::numeric_limits::max(); } template::value>::type = sprout::enabler> static SPROUT_CONSTEXPR T default_value() { return T(); } private: value_type current_; public: SPROUT_CONSTEXPR counting_iterator() : current_(default_value()) {} 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 SPROUT_CXX14_CONSTEXPR 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_; } SPROUT_CXX14_CONSTEXPR counting_iterator& operator++() { ++current_; return *this; } SPROUT_CXX14_CONSTEXPR counting_iterator operator++(int) { counting_iterator result(*this); ++current_; return result; } SPROUT_CXX14_CONSTEXPR counting_iterator& operator--() { --current_; return *this; } SPROUT_CXX14_CONSTEXPR 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); } SPROUT_CXX14_CONSTEXPR counting_iterator& operator+=(difference_type n) { counting_iterator temp(current_ + n); temp.swap(*this); return *this; } SPROUT_CXX14_CONSTEXPR 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); } SPROUT_CXX14_CONSTEXPR void swap(counting_iterator& other) SPROUT_NOEXCEPT_IF_EXPR(sprout::swap(current_, other.current_)) { sprout::swap(current_, other.current_); } }; template inline SPROUT_CONSTEXPR bool operator==(sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs) { return *lhs == *rhs; } template inline SPROUT_CONSTEXPR bool operator!=(sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs) { return !(lhs == rhs); } template inline SPROUT_CONSTEXPR bool operator<(sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs) { return *lhs < *rhs; } template inline SPROUT_CONSTEXPR bool operator>(sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs) { return rhs < lhs; } template inline SPROUT_CONSTEXPR bool operator<=(sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs) { return !(rhs < lhs); } template inline SPROUT_CONSTEXPR bool operator>=(sprout::counting_iterator const& lhs, sprout::counting_iterator const& rhs) { return !(lhs < rhs); } template inline 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 inline 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 inline SPROUT_CONSTEXPR sprout::counting_iterator make_counting_iterator(Incrementable const& v) { return sprout::counting_iterator(v); } // // swap // template inline SPROUT_CXX14_CONSTEXPR void swap(sprout::counting_iterator& lhs, sprout::counting_iterator& rhs) SPROUT_NOEXCEPT_IF_EXPR(lhs.swap(rhs)) { lhs.swap(rhs); } // // iterator_next // template inline SPROUT_CONSTEXPR sprout::counting_iterator iterator_next(sprout::counting_iterator const& it) { return it.next(); } // // iterator_prev // template inline SPROUT_CONSTEXPR sprout::counting_iterator iterator_prev(sprout::counting_iterator const& it) { return it.prev(); } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_COUNTING_ITERATOR_HPP