#ifndef SPROUT_ITERATOR_PREV_HPP #define SPROUT_ITERATOR_PREV_HPP #include #include #include #include namespace sprout { namespace detail { template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_literal_type::type>::value, typename std::decay::type >::type prev_impl( RandomAccessIterator&& it, std::random_access_iterator_tag* ) { return sprout::forward(it) - 1; } template inline SPROUT_CONSTEXPR typename std::decay::type prev_impl( BidirectionalIterator&& it, void* ) { using std::prev; return prev(sprout::forward(it)); } template inline SPROUT_CONSTEXPR typename std::enable_if< std::is_literal_type::type>::value, typename std::decay::type >::type prev_impl( RandomAccessIterator&& it, typename std::iterator_traits::type>::difference_type n, std::random_access_iterator_tag* ) { return sprout::forward(it) - n; } template inline SPROUT_CONSTEXPR typename std::decay::type prev_impl( BidirectionalIterator it, typename std::iterator_traits::type>::difference_type n, void* ) { using std::prev; return prev(sprout::forward(it), n); } } // namespace detail // // prev // template inline SPROUT_CONSTEXPR typename std::decay::type prev(BidirectionalIterator&& it) { typedef typename std::iterator_traits::type>::iterator_category* category; return sprout::detail::prev_impl( sprout::forward(it), category() ); } template inline SPROUT_CONSTEXPR typename std::decay::type prev(BidirectionalIterator&& it, typename std::iterator_traits::type>::difference_type n) { typedef typename std::iterator_traits::type>::iterator_category* category; return sprout::detail::prev_impl( sprout::forward(it), n, category() ); } } // namespace sprout #endif // #ifndef SPROUT_ITERATOR_PREV_HPP