#ifndef SPROUT_ITERATOR_REVERSE_ITERATOR_HPP #define SPROUT_ITERATOR_REVERSE_ITERATOR_HPP #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; SPROUT_CONSTEXPR explicit 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); } 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 bool operator<( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return lhs.base() < rhs.base(); } template bool operator>( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return rhs < lhs; } template bool operator<=( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return !(rhs < lhs); } template bool operator>=( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) { return !(lhs < rhs); } template auto operator-( sprout::reverse_iterator const& lhs, sprout::reverse_iterator const& rhs ) -> decltype(lhs.current - rhs.current) { return lhs.current - rhs.current; } 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); } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_REVERSE_ITERATOR_HPP