#ifndef SPROUT_ITERATOR_CLAMP_ITERATOR_HPP #define SPROUT_ITERATOR_CLAMP_ITERATOR_HPP #include #include #include #include #include #include #include #include HDR_FUNCTIONAL_SSCRISK_CEL_OR_SPROUT namespace sprout { // // clamp_iterator // template::value_type> > class clamp_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 Compare compare_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; compare_type comp; value_type low; value_type up; private: public: clamp_iterator() = default; clamp_iterator(clamp_iterator const&) = default; SPROUT_CONSTEXPR clamp_iterator(iterator_type it, value_type const& low, value_type const& up, compare_type comp = compare_type()) : current(it), comp(comp), low(low), up(up) {} template SPROUT_CONSTEXPR clamp_iterator(clamp_iterator const& it) : current(it.current), comp(it.comp), low(it.low), up(it.up) {} template clamp_iterator& operator=(clamp_iterator const& it) { clamp_iterator temp(it); temp.swap(*this); return *this; } SPROUT_CONSTEXPR iterator_type const& base() const { return current; } SPROUT_CONSTEXPR compare_type const& compare() const { return comp; } SPROUT_CONSTEXPR value_type const& lower() const { return low; } SPROUT_CONSTEXPR value_type const& upper() const { return up; } SPROUT_CONSTEXPR reference operator*() const { return sprout::clamp(*current, low, up, comp); } SPROUT_CONSTEXPR pointer operator->() const { return &sprout::clamp(*current, low, up, comp); } clamp_iterator& operator++() { ++current; return *this; } clamp_iterator operator++(int) { clamp_iterator result(*this); ++current; return result; } clamp_iterator& operator--() { --current; return *this; } clamp_iterator operator--(int) { clamp_iterator temp(*this); --current; return temp; } SPROUT_CONSTEXPR clamp_iterator operator+(difference_type n) const { return clamp_iterator(sprout::next(current, n), low, up, comp); } SPROUT_CONSTEXPR clamp_iterator operator-(difference_type n) const { return clamp_iterator(sprout::prev(current, n), low, up, comp); } clamp_iterator& operator+=(difference_type n) { clamp_iterator temp(sprout::next(current, n), low, up, comp); temp.swap(*this); return *this; } clamp_iterator& operator-=(difference_type n) { clamp_iterator temp(sprout::prev(current, n), low, up, comp); temp.swap(*this); return *this; } SPROUT_CONSTEXPR reference operator[](difference_type n) const { return sprout::clamp(*sprout::next(current, n), low, up, comp); } SPROUT_CONSTEXPR clamp_iterator next() const { return clamp_iterator(sprout::next(current), low, up, comp); } SPROUT_CONSTEXPR clamp_iterator prev() const { return clamp_iterator(sprout::prev(current), low, up, comp); } void swap(clamp_iterator& other) SPROUT_NOEXCEPT_EXPR( SPROUT_NOEXCEPT_EXPR(sprout::swap(current, other.current)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(comp, other.comp)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(low, other.low)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(up, other.up)) ) { sprout::swap(current, other.current); sprout::swap(comp, other.comp); sprout::swap(low, other.low); sprout::swap(up, other.up); } }; template inline SPROUT_CONSTEXPR bool operator==( sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs ) { return lhs.base() == rhs.base(); } template inline SPROUT_CONSTEXPR bool operator!=(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { return !(lhs == rhs); } template inline SPROUT_CONSTEXPR bool operator<(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { return lhs.base() < rhs.base(); } template inline SPROUT_CONSTEXPR bool operator>(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { return rhs < lhs; } template inline SPROUT_CONSTEXPR bool operator<=(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { return !(rhs < lhs); } template inline SPROUT_CONSTEXPR bool operator>=(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { return !(lhs < rhs); } template inline SPROUT_CONSTEXPR decltype(std::declval() - std::declval()) operator-(sprout::clamp_iterator const& lhs, sprout::clamp_iterator const& rhs) { return lhs.base() - rhs.base(); } template inline SPROUT_CONSTEXPR sprout::clamp_iterator operator+( typename sprout::clamp_iterator::difference_type n, sprout::clamp_iterator const& it ) { return it + n; } // // make_clamp_iterator // template inline SPROUT_CONSTEXPR sprout::clamp_iterator make_clamp_iterator( Iterator it, typename std::iterator_traits::value_type const& low, typename std::iterator_traits::value_type const& up, Compare comp ) { return sprout::clamp_iterator(it, low, up, comp); } template inline SPROUT_CONSTEXPR sprout::clamp_iterator make_clamp_iterator( Iterator it, typename std::iterator_traits::value_type const& low, typename std::iterator_traits::value_type const& up ) { return sprout::clamp_iterator(it, low, up); } // // swap // template inline void swap(sprout::clamp_iterator& lhs, sprout::clamp_iterator& rhs) SPROUT_NOEXCEPT_EXPR(SPROUT_NOEXCEPT_EXPR(lhs.swap(rhs))) { lhs.swap(rhs); } // // iterator_distance // template inline SPROUT_CONSTEXPR typename std::iterator_traits >::difference_type iterator_distance(sprout::clamp_iterator first, sprout::clamp_iterator last) { return last - first; } // // iterator_next // template inline SPROUT_CONSTEXPR sprout::clamp_iterator iterator_next(sprout::clamp_iterator const& it) { return it.next(); } template inline SPROUT_CONSTEXPR sprout::clamp_iterator iterator_next( sprout::clamp_iterator const& it, typename sprout::clamp_iterator::difference_type n ) { return it + n; } // // iterator_prev // template inline SPROUT_CONSTEXPR sprout::clamp_iterator iterator_prev(sprout::clamp_iterator const& it) { return it.prev(); } template inline SPROUT_CONSTEXPR sprout::clamp_iterator iterator_prev( sprout::clamp_iterator const& it, typename sprout::clamp_iterator::difference_type n ) { return it - n; } } // namespace sprout #endif // SPROUT_ITERATOR_CLAMP_ITERATOR_HPP