/*============================================================================= 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_TRANSFORM_ITERATOR_HPP #define SPROUT_ITERATOR_TRANSFORM_ITERATOR_HPP #include #include #include #include #include #include #include #include #include namespace sprout { // // transform_iterator // template class transform_iterator : public std::iterator< typename sprout::common_iterator_category::type, typename std::remove_reference< typename std::result_of< BinaryFunction ( typename std::iterator_traits::reference, typename std::iterator_traits::reference ) >::type >::type, typename std::iterator_traits::difference_type, typename std::remove_reference< typename std::result_of< BinaryFunction ( typename std::iterator_traits::reference, typename std::iterator_traits::reference ) >::type >::type*, typename std::result_of< BinaryFunction ( typename std::iterator_traits::reference, typename std::iterator_traits::reference ) >::type > { public: typedef BinaryFunction functor_type; typedef LIterator iterator_type; typedef RIterator iterator2_type; typedef typename sprout::common_iterator_category::type iterator_category; typedef typename std::result_of< BinaryFunction ( typename std::iterator_traits::reference, typename std::iterator_traits::reference ) >::type reference; typedef typename std::remove_reference::type value_type; typedef typename std::iterator_traits::difference_type difference_type; typedef value_type* pointer; protected: iterator_type current; iterator2_type current2; BinaryFunction func; public: SPROUT_CONSTEXPR transform_iterator() : current(), current2(), func() {} transform_iterator(transform_iterator const&) = default; SPROUT_CONSTEXPR transform_iterator(iterator_type it, iterator2_type it2) : current(it) , current2(it2) {} SPROUT_CONSTEXPR transform_iterator(iterator_type it, iterator2_type it2, BinaryFunction func) : current(it) , current2(it2) , func(func) {} template SPROUT_CONSTEXPR transform_iterator(transform_iterator const& it) : current(it.current) , current2(it.current2) , func(it.func) {} template SPROUT_CXX14_CONSTEXPR transform_iterator& operator=(transform_iterator const& it) { transform_iterator temp(it); temp.swap(*this); return *this; } SPROUT_CONSTEXPR iterator_type base() const { return current; } SPROUT_CONSTEXPR iterator_type base2() const { return current2; } SPROUT_CONSTEXPR BinaryFunction functor() const { return func; } SPROUT_CONSTEXPR reference operator*() const { return func(*current, *current2); } SPROUT_CONSTEXPR pointer operator->() const { return &func(*current, *current2); } SPROUT_CXX14_CONSTEXPR transform_iterator& operator++() { ++current; ++current2; return *this; } SPROUT_CXX14_CONSTEXPR transform_iterator operator++(int) { transform_iterator result(*this); ++current; ++current2; return result; } SPROUT_CXX14_CONSTEXPR transform_iterator& operator--() { --current; --current2; return *this; } SPROUT_CXX14_CONSTEXPR transform_iterator operator--(int) { transform_iterator temp(*this); --current; --current2; return temp; } SPROUT_CONSTEXPR transform_iterator operator+(difference_type n) const { return transform_iterator(current + n, current2 + n, func); } SPROUT_CONSTEXPR transform_iterator operator-(difference_type n) const { return transform_iterator(current - n, current2 - n, func); } SPROUT_CXX14_CONSTEXPR transform_iterator& operator+=(difference_type n) { transform_iterator temp(current + n, current2 + n, func); temp.swap(*this); return *this; } SPROUT_CXX14_CONSTEXPR transform_iterator& operator-=(difference_type n) { transform_iterator temp(current - n, current2 - n, func); temp.swap(*this); return *this; } SPROUT_CONSTEXPR reference operator[](difference_type n) const { return func(current[n], current2[n]); } SPROUT_CONSTEXPR transform_iterator next() const { return transform_iterator(sprout::next(current), sprout::next(current2), func); } SPROUT_CONSTEXPR transform_iterator prev() const { return transform_iterator(sprout::prev(current), sprout::prev(current2), func); } SPROUT_CXX14_CONSTEXPR void swap(transform_iterator& other) SPROUT_NOEXCEPT_IF( SPROUT_NOEXCEPT_EXPR(sprout::swap(current, other.current)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(current2, other.current2)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(func, other.func)) ) { sprout::swap(current, other.current); sprout::swap(current2, other.current2); sprout::swap(func, other.func); } }; // // transform_iterator // template class transform_iterator : public std::iterator< typename std::iterator_traits::iterator_category, typename std::remove_reference< typename std::result_of< UnaryFunction (typename std::iterator_traits::reference) >::type >::type, typename std::iterator_traits::difference_type, typename std::remove_reference< typename std::result_of< UnaryFunction (typename std::iterator_traits::reference) >::type >::type*, typename std::result_of< UnaryFunction (typename std::iterator_traits::reference) >::type > { public: typedef UnaryFunction functor_type; typedef Iterator iterator_type; typedef typename std::iterator_traits::iterator_category iterator_category; typedef typename std::result_of< UnaryFunction (typename std::iterator_traits::reference) >::type reference; typedef typename std::remove_reference::type value_type; typedef typename std::iterator_traits::difference_type difference_type; typedef value_type* pointer; protected: iterator_type current; UnaryFunction func; public: SPROUT_CONSTEXPR transform_iterator() : current(), func() {} transform_iterator(transform_iterator const&) = default; explicit SPROUT_CONSTEXPR transform_iterator(iterator_type it) : current(it) {} SPROUT_CONSTEXPR transform_iterator(iterator_type it, UnaryFunction func) : current(it) , func(func) {} template SPROUT_CONSTEXPR transform_iterator(transform_iterator const& it) : current(it.current) , func(it.func) {} template SPROUT_CXX14_CONSTEXPR transform_iterator& operator=(transform_iterator const& it) { transform_iterator temp(it); temp.swap(*this); return *this; } SPROUT_CONSTEXPR iterator_type base() const { return current; } SPROUT_CONSTEXPR UnaryFunction functor() const { return func; } SPROUT_CONSTEXPR reference operator*() const { return func(*current); } SPROUT_CONSTEXPR pointer operator->() const { return &func(*current); } SPROUT_CXX14_CONSTEXPR transform_iterator& operator++() { ++current; return *this; } SPROUT_CXX14_CONSTEXPR transform_iterator operator++(int) { transform_iterator result(*this); ++current; return result; } SPROUT_CXX14_CONSTEXPR transform_iterator& operator--() { --current; return *this; } SPROUT_CXX14_CONSTEXPR transform_iterator operator--(int) { transform_iterator temp(*this); --current; return temp; } SPROUT_CONSTEXPR transform_iterator operator+(difference_type n) const { return transform_iterator(current + n, func); } SPROUT_CONSTEXPR transform_iterator operator-(difference_type n) const { return transform_iterator(current - n, func); } SPROUT_CXX14_CONSTEXPR transform_iterator& operator+=(difference_type n) { transform_iterator temp(current + n, func); temp.swap(*this); return *this; } SPROUT_CXX14_CONSTEXPR transform_iterator& operator-=(difference_type n) { transform_iterator temp(current - n, func); temp.swap(*this); return *this; } SPROUT_CONSTEXPR reference operator[](difference_type n) const { return func(current[n]); } SPROUT_CONSTEXPR transform_iterator next() const { return transform_iterator(sprout::next(current), func); } SPROUT_CONSTEXPR transform_iterator prev() const { return transform_iterator(sprout::prev(current), func); } SPROUT_CXX14_CONSTEXPR void swap(transform_iterator& other) SPROUT_NOEXCEPT_IF( SPROUT_NOEXCEPT_EXPR(sprout::swap(current, other.current)) && SPROUT_NOEXCEPT_EXPR(sprout::swap(func, other.func)) ) { sprout::swap(current, other.current); sprout::swap(func, other.func); } }; template< typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1, typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2 > inline SPROUT_CONSTEXPR bool operator==( sprout::transform_iterator const& lhs, sprout::transform_iterator const& rhs ) { return lhs.base() == rhs.base(); } template< typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1, typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2 > inline SPROUT_CONSTEXPR bool operator!=( sprout::transform_iterator const& lhs, sprout::transform_iterator const& rhs ) { return !(lhs == rhs); } template< typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1, typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2 > inline SPROUT_CONSTEXPR bool operator<( sprout::transform_iterator const& lhs, sprout::transform_iterator const& rhs ) { return lhs.base() < rhs.base(); } template< typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1, typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2 > inline SPROUT_CONSTEXPR bool operator>( sprout::transform_iterator const& lhs, sprout::transform_iterator const& rhs ) { return rhs < lhs; } template< typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1, typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2 > inline SPROUT_CONSTEXPR bool operator<=( sprout::transform_iterator const& lhs, sprout::transform_iterator const& rhs ) { return !(rhs < lhs); } template< typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1, typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2 > inline SPROUT_CONSTEXPR bool operator>=( sprout::transform_iterator const& lhs, sprout::transform_iterator const& rhs ) { return !(lhs < rhs); } template< typename UnaryOrBinaryFunction1, typename LIterator1, typename RIterator1, typename UnaryOrBinaryFunction2, typename LIterator2, typename RIterator2 > inline SPROUT_CONSTEXPR decltype(std::declval() - std::declval()) operator-( sprout::transform_iterator const& lhs, sprout::transform_iterator const& rhs ) { return lhs.base() - rhs.base(); } template inline SPROUT_CONSTEXPR sprout::transform_iterator operator+( typename sprout::transform_iterator::difference_type n, sprout::transform_iterator const& it ) { return it + n; } // // make_transform_iterator // template inline SPROUT_CONSTEXPR sprout::transform_iterator make_transform_iterator(LIterator it1, RIterator it2, BinaryFunction func) { return sprout::transform_iterator(it1, it2, func); } template inline SPROUT_CONSTEXPR sprout::transform_iterator make_transform_iterator(Iterator it, UnaryFunction func) { return sprout::transform_iterator(it, func); } // // swap // template inline SPROUT_CXX14_CONSTEXPR void swap( sprout::transform_iterator& lhs, sprout::transform_iterator& rhs ) SPROUT_NOEXCEPT_IF_EXPR(lhs.swap(rhs)) { lhs.swap(rhs); } // // iterator_next // template inline SPROUT_CONSTEXPR sprout::transform_iterator iterator_next(sprout::transform_iterator const& it) { return it.next(); } // // iterator_prev // template inline SPROUT_CONSTEXPR sprout::transform_iterator iterator_prev(sprout::transform_iterator const& it) { return it.prev(); } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_TRANSFORM_ITERATOR_HPP