#ifndef SPROUT_ITERATOR_REVERSE_ITERATOR_HPP #define SPROUT_ITERATOR_REVERSE_ITERATOR_HPP #include #include #include #include #include #include namespace sprout { // // reverse_iterator // template class reverse_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: typedef Iterator iterator_type; typedef typename std::iterator_traits::iterator_category iterator_category; typedef typename std::iterator_traits::value_type value_type; typedef typename std::iterator_traits::difference_type difference_type; typedef typename std::iterator_traits::pointer pointer; typedef typename std::iterator_traits::reference reference; protected: iterator_type current; private: iterator_type deref_tmp; public: reverse_iterator() = default; reverse_iterator(reverse_iterator const&) = default; explicit SPROUT_CONSTEXPR reverse_iterator(iterator_type it) : current(it) , deref_tmp(sprout::prev(it)) {} template SPROUT_CONSTEXPR reverse_iterator(reverse_iterator const& it) : current(it) , deref_tmp(sprout::prev(it)) {} template reverse_iterator& operator=(reverse_iterator const& it) { reverse_iterator temp(it); temp.swap(*this); return *this; } SPROUT_CONSTEXPR iterator_type base() const { return current; } SPROUT_CONSTEXPR reference operator*() const { return *deref_tmp; } SPROUT_CONSTEXPR pointer operator->() const { return &*deref_tmp; } reverse_iterator& operator++() { --current; --deref_tmp; return *this; } reverse_iterator operator++(int) { reverse_iterator result(*this); --current; --deref_tmp; return result; } reverse_iterator& operator--() { ++current; ++deref_tmp; return *this; } reverse_iterator operator--(int) { reverse_iterator temp(*this); ++current; ++deref_tmp; return temp; } SPROUT_CONSTEXPR reverse_iterator operator+(difference_type n) const { return reverse_iterator(current - n); } SPROUT_CONSTEXPR reverse_iterator operator-(difference_type n) const { return reverse_iterator(current + n); } reverse_iterator& operator+=(difference_type n) { reverse_iterator temp(current - n); temp.swap(*this); return *this; } reverse_iterator& operator-=(difference_type n) { reverse_iterator temp(current + n); temp.swap(*this); return *this; } SPROUT_CONSTEXPR reference operator[](difference_type n) const { return *(deref_tmp - n); } SPROUT_CONSTEXPR reverse_iterator next() const { return reverse_iterator(sprout::prev(current)); } SPROUT_CONSTEXPR reverse_iterator prev() const { return reverse_iterator(sprout::next(current)); } void swap(reverse_iterator& other) { using std::swap; swap(current, other.current); swap(deref_tmp, other.deref_tmp); } }; template SPROUT_CONSTEXPR bool operator==( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return lhs.base() == rhs.base(); } template SPROUT_CONSTEXPR bool operator!=( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return !(lhs == rhs); } template SPROUT_CONSTEXPR bool operator<( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return lhs.base() < rhs.base(); } template SPROUT_CONSTEXPR bool operator>( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return rhs < lhs; } template SPROUT_CONSTEXPR bool operator<=( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return !(rhs < lhs); } template SPROUT_CONSTEXPR bool operator>=( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return !(lhs < rhs); } template SPROUT_CONSTEXPR decltype(std::declval() - std::declval()) operator-( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return lhs.base() - rhs.base(); } template SPROUT_CONSTEXPR sprout::reverse_iterator operator+( typename sprout::reverse_iterator::difference_type n, sprout::reverse_iterator const& it ) { return it + n; } // // swap // template void swap(sprout::reverse_iterator& lhs, sprout::reverse_iterator& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } // // next // template SPROUT_CONSTEXPR sprout::reverse_iterator next( sprout::reverse_iterator const& it ) { return it.next(); } template SPROUT_CONSTEXPR sprout::reverse_iterator next( sprout::reverse_iterator const& it, typename sprout::reverse_iterator::difference_type n ) { return it + n; } // // prev // template SPROUT_CONSTEXPR sprout::reverse_iterator prev( sprout::reverse_iterator const& it ) { return it.prev(); } template SPROUT_CONSTEXPR sprout::reverse_iterator prev( sprout::reverse_iterator const& it, typename sprout::reverse_iterator::difference_type n ) { return it - n; } // // distance // template SPROUT_CONSTEXPR typename std::iterator_traits >::difference_type distance( sprout::reverse_iterator first, sprout::reverse_iterator last ) { return last - first; } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_REVERSE_ITERATOR_HPP