/*============================================================================= 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_INDEX_ITERATOR_HPP #define SPROUT_ITERATOR_INDEX_ITERATOR_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace sprout { // // index_iterator // template class index_iterator : public std::iterator< std::random_access_iterator_tag, typename sprout::container_traits::type>::value_type, typename sprout::container_traits::type>::difference_type, typename std::conditional< std::is_const::type>::value, typename sprout::container_traits::type>::const_pointer, typename sprout::container_traits::type>::pointer >::type, typename std::conditional< std::is_const::type>::value, typename sprout::container_traits::type>::const_reference, typename sprout::container_traits::type>::reference >::type > , public sprout::detail::iterator_to_pointer_base< sprout::index_iterator, typename std::conditional< std::is_const::type>::value, typename sprout::container_traits::type>::const_pointer, typename sprout::container_traits::type>::pointer >::type, ConvertibleToPointer > { public: typedef Container container_type; typedef typename sprout::container_traits::type> traits_type; typedef typename std::conditional< std::is_reference::value, typename std::remove_reference::type const&, typename std::remove_reference::type const >::type const_container_type; private: typedef std::iterator< std::random_access_iterator_tag, typename traits_type::value_type, typename traits_type::difference_type, typename std::conditional< std::is_const::type>::value, typename traits_type::const_pointer, typename traits_type::pointer >::type, typename std::conditional< std::is_const::type>::value, typename traits_type::const_reference, typename traits_type::reference >::type > base_type; typedef sprout::value_holder holder_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 traits_type::size_type size_type; private: holder_type holder_; difference_type index_; private: SPROUT_CONSTEXPR index_iterator(holder_type const& r, difference_type index) : holder_(r), index_(index) {} public: SPROUT_CONSTEXPR index_iterator() : holder_(), index_() {} index_iterator(index_iterator const&) = default; explicit SPROUT_CONSTEXPR index_iterator(typename holder_type::param_type p) : holder_(p), index_(0) {} SPROUT_CONSTEXPR index_iterator(typename holder_type::param_type p, difference_type index) : holder_(p), index_(index) {} SPROUT_CONSTEXPR operator index_iterator() const { return index_iterator(holder_.get(), index_); } SPROUT_CONSTEXPR typename holder_type::mutable_or_const_reference base() const { return holder_.get(); } SPROUT_CONSTEXPR difference_type index() const { return index_; } SPROUT_CONSTEXPR index_iterator next() const { return index_iterator(holder_, index_ + 1); } SPROUT_CONSTEXPR index_iterator prev() const { return index_iterator(holder_, index_ - 1); } SPROUT_CXX14_CONSTEXPR void swap(index_iterator& other) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(sprout::swap(holder_, other.holder_))) { sprout::swap(holder_, other.holder_); sprout::swap(index_, other.index_); } SPROUT_CONSTEXPR reference operator*() const { return holder_.get()[index_]; } SPROUT_CONSTEXPR pointer operator->() const { return &holder_.get()[index_]; } SPROUT_CXX14_CONSTEXPR index_iterator& operator++() { index_iterator temp(next()); temp.swap(*this); return *this; } SPROUT_CXX14_CONSTEXPR index_iterator operator++(int) { index_iterator result(*this); ++*this; return result; } SPROUT_CXX14_CONSTEXPR index_iterator& operator--() { index_iterator temp(prev()); temp.swap(*this); return *this; } SPROUT_CXX14_CONSTEXPR index_iterator operator--(int) { index_iterator result(*this); --*this; return result; } SPROUT_CONSTEXPR index_iterator operator+(difference_type n) const { return index_iterator(holder_, index_ + n); } SPROUT_CONSTEXPR index_iterator operator-(difference_type n) const { return index_iterator(holder_, index_ - n); } SPROUT_CXX14_CONSTEXPR index_iterator& operator+=(difference_type n) { index_iterator temp(holder_, index_ + n); temp.swap(*this); return *this; } SPROUT_CXX14_CONSTEXPR index_iterator& operator-=(difference_type n) { index_iterator temp(holder_, index_ - n); temp.swap(*this); return *this; } SPROUT_CONSTEXPR reference operator[](difference_type n) const { return holder_.get()[index_ + n]; } }; template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_same::type, typename std::decay::type>::value, bool >::type operator==(sprout::index_iterator const& lhs, sprout::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::index_iterator const& lhs, sprout::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::index_iterator const& lhs, sprout::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::index_iterator const& lhs, sprout::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::index_iterator const& lhs, sprout::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::index_iterator const& lhs, sprout::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::index_iterator const& lhs, sprout::index_iterator const& rhs) { return lhs.index() - rhs.index(); } template inline SPROUT_CONSTEXPR sprout::index_iterator operator+(typename sprout::index_iterator::difference_type n, sprout::index_iterator const& it) { return it + n; } // // swap // template inline SPROUT_CXX14_CONSTEXPR void swap(sprout::index_iterator& lhs, sprout::index_iterator& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } // // is_index_iterator // template struct is_index_iterator : public sprout::false_type {}; template struct is_index_iterator : public sprout::is_index_iterator {}; template struct is_index_iterator : public sprout::is_index_iterator {}; template struct is_index_iterator > : public sprout::true_type {}; // // iterator_next // template inline SPROUT_CONSTEXPR sprout::index_iterator iterator_next(sprout::index_iterator const& it) { return it.next(); } // // iterator_prev // template inline SPROUT_CONSTEXPR sprout::index_iterator iterator_prev(sprout::index_iterator const& it) { return it.prev(); } // // is_const_iterator_cast_convertible // template struct is_const_iterator_cast_convertible, sprout::index_iterator > : public std::is_same::type, typename std::decay::type> {}; // // const_iterator_conversion // template< typename T, typename Container, bool C, typename sprout::enabler_if, T>::value>::type = sprout::enabler > inline SPROUT_CONSTEXPR T const_iterator_conversion(sprout::index_iterator const& it) { return T(const_cast(it.base()), it.index()); } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_INDEX_ITERATOR_HPP