/*============================================================================= Copyright (c) 2011-2014 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_PTR_INDEX_ITERATOR_HPP #define SPROUT_ITERATOR_PTR_INDEX_ITERATOR_HPP #include #include #include #include #include #include #include #include #include #include namespace sprout { // // ptr_index_iterator // template class ptr_index_iterator : public std::iterator< typename std::iterator_traits::iterator_category, typename std::iterator_traits::value_type, typename std::iterator_traits::difference_type, typename std::iterator_traits::pointer, typename std::iterator_traits::reference > , public sprout::detail::iterator_to_pointer_base< sprout::ptr_index_iterator, typename std::iterator_traits::pointer, ConvertibleToPointer > { public: typedef T type; private: typedef std::iterator< typename std::iterator_traits::iterator_category, typename std::iterator_traits::value_type, typename std::iterator_traits::difference_type, typename std::iterator_traits::pointer, typename std::iterator_traits::reference > base_type; public: typedef typename base_type::iterator_category iterator_category; typedef typename base_type::value_type value_type; typedef typename base_type::difference_type difference_type; typedef typename base_type::pointer pointer; typedef typename base_type::reference reference; typedef typename std::remove_pointer::type const* const_pointer; private: pointer p_; difference_type index_; public: SPROUT_CONSTEXPR ptr_index_iterator() : p_(), index_() {} ptr_index_iterator(ptr_index_iterator const&) = default; explicit SPROUT_CONSTEXPR ptr_index_iterator(pointer p) : p_(p), index_(0) {} SPROUT_CONSTEXPR ptr_index_iterator(pointer p, difference_type index) : p_(p), index_(index) {} SPROUT_CONSTEXPR operator ptr_index_iterator() const { return ptr_index_iterator(p_, index_); } SPROUT_CONSTEXPR pointer base() const { return p_; } SPROUT_CONSTEXPR difference_type index() const { return index_; } SPROUT_CONSTEXPR pointer ptr() const { return p_ + index_; } SPROUT_CONSTEXPR ptr_index_iterator next() const { return ptr_index_iterator(p_, index_ + 1); } SPROUT_CONSTEXPR ptr_index_iterator prev() const { return ptr_index_iterator(p_, index_ - 1); } SPROUT_CXX14_CONSTEXPR void swap(ptr_index_iterator& other) SPROUT_NOEXCEPT { sprout::swap(p_, other.p_); sprout::swap(index_, other.index_); } SPROUT_CONSTEXPR reference operator*() const { return p_[index_]; } SPROUT_CONSTEXPR pointer operator->() const { return p_ + index_; } SPROUT_CXX14_CONSTEXPR ptr_index_iterator& operator++() { ptr_index_iterator temp(next()); temp.swap(*this); return *this; } SPROUT_CXX14_CONSTEXPR ptr_index_iterator operator++(int) { ptr_index_iterator result(*this); ++*this; return result; } SPROUT_CXX14_CONSTEXPR ptr_index_iterator& operator--() { ptr_index_iterator temp(prev()); temp.swap(*this); return *this; } SPROUT_CXX14_CONSTEXPR ptr_index_iterator operator--(int) { ptr_index_iterator result(*this); --*this; return result; } SPROUT_CONSTEXPR ptr_index_iterator operator+(difference_type n) const { return ptr_index_iterator(p_, index_ + n); } SPROUT_CONSTEXPR ptr_index_iterator operator-(difference_type n) const { return ptr_index_iterator(p_, index_ - n); } SPROUT_CXX14_CONSTEXPR ptr_index_iterator& operator+=(difference_type n) { ptr_index_iterator temp(p_, index_ + n); temp.swap(*this); return *this; } SPROUT_CXX14_CONSTEXPR ptr_index_iterator& operator-=(difference_type n) { ptr_index_iterator temp(p_, index_ - n); temp.swap(*this); return *this; } SPROUT_CONSTEXPR reference operator[](difference_type n) const { return p_[index_ + n]; } }; template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_same::type, typename std::decay::type>::value, bool >::type operator==(sprout::ptr_index_iterator const& lhs, sprout::ptr_index_iterator const& rhs) { return lhs.index() == rhs.index(); } template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_same::type, typename std::decay::type>::value, bool >::type operator!=(sprout::ptr_index_iterator const& lhs, sprout::ptr_index_iterator const& rhs) { return !(lhs == rhs); } template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_same::type, typename std::decay::type>::value, bool >::type operator<(sprout::ptr_index_iterator const& lhs, sprout::ptr_index_iterator const& rhs) { return lhs.index() < rhs.index(); } template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_same::type, typename std::decay::type>::value, bool >::type operator>(sprout::ptr_index_iterator const& lhs, sprout::ptr_index_iterator const& rhs) { return rhs < lhs; } template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_same::type, typename std::decay::type>::value, bool >::type operator<=(sprout::ptr_index_iterator const& lhs, sprout::ptr_index_iterator const& rhs) { return !(rhs < lhs); } template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_same::type, typename std::decay::type>::value, bool >::type operator>=(sprout::ptr_index_iterator const& lhs, sprout::ptr_index_iterator const& rhs) { return !(lhs < rhs); } template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_same::type, typename std::decay::type>::value, decltype( std::declval >::difference_type>() - std::declval >::difference_type>() ) >::type operator-(sprout::ptr_index_iterator const& lhs, sprout::ptr_index_iterator const& rhs) { return lhs.index() - rhs.index(); } template inline SPROUT_CONSTEXPR sprout::ptr_index_iterator operator+(typename sprout::ptr_index_iterator::difference_type n, sprout::ptr_index_iterator const& it) { return it + n; } // // swap // template inline SPROUT_CXX14_CONSTEXPR void swap(sprout::ptr_index_iterator& lhs, sprout::ptr_index_iterator& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } // // make_ptr_index_iterator // template inline SPROUT_CONSTEXPR sprout::ptr_index_iterator make_ptr_index_iterator(T* p) { return sprout::ptr_index_iterator(p); } template inline SPROUT_CONSTEXPR sprout::ptr_index_iterator make_ptr_index_iterator(T* p, typename sprout::ptr_index_iterator::difference_type index) { return sprout::ptr_index_iterator(p, index); } // // ptr_index // template inline SPROUT_CONSTEXPR sprout::ptr_index_iterator ptr_index(T* p) { return sprout::make_ptr_index_iterator(p); } template inline SPROUT_CONSTEXPR sprout::ptr_index_iterator ptr_index(T* p, typename std::iterator_traits::difference_type n) { return sprout::make_ptr_index_iterator(p, n); } template inline SPROUT_CONSTEXPR Iterator ptr_index(Iterator const& it) { return it; } template inline SPROUT_CONSTEXPR Iterator ptr_index(Iterator const& it, typename std::iterator_traits::difference_type n) { return sprout::next(it, n); } // // ptr_unindex // template inline SPROUT_CONSTEXPR typename sprout::ptr_index_iterator::pointer ptr_unindex(sprout::ptr_index_iterator const& it) { return it.ptr(); } template inline SPROUT_CONSTEXPR Iterator ptr_unindex(Iterator const& it) { return it; } // // is_ptr_index_iterator // template struct is_ptr_index_iterator : public sprout::false_type {}; template struct is_ptr_index_iterator : public sprout::is_ptr_index_iterator {}; template struct is_ptr_index_iterator : public sprout::is_ptr_index_iterator {}; template struct is_ptr_index_iterator > : public sprout::true_type {}; // // iterator_next // template inline SPROUT_CONSTEXPR sprout::ptr_index_iterator iterator_next(sprout::ptr_index_iterator const& it) { return it.next(); } // // iterator_prev // template inline SPROUT_CONSTEXPR sprout::ptr_index_iterator iterator_prev(sprout::ptr_index_iterator const& it) { return it.prev(); } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_PTR_INDEX_ITERATOR_HPP