diff --git a/alib2std/src/extensions/iterator.hpp b/alib2std/src/extensions/iterator.hpp index 1373c176b8fb94db993086f6b71c1affaf9518e3..8ea3da5a2706ab9acdcaa2d02e7fd81f75955162 100644 --- a/alib2std/src/extensions/iterator.hpp +++ b/alib2std/src/extensions/iterator.hpp @@ -176,6 +176,36 @@ struct is_iterator : std::false_type {}; template < typename T > struct is_iterator<typename std::iterator_traits<T>> : std::true_type {}; +template < typename BidirectionalIterator, typename Distance > +inline constexpr void retractInternal ( BidirectionalIterator & i, Distance n, std::bidirectional_iterator_tag ) { + while ( n -- ) + -- i; + while ( n ++ ) + ++ i; +} + +template < typename RandomAccessIterator, typename Distance > +inline constexpr void retractInternal ( RandomAccessIterator & i, Distance n, std::random_access_iterator_tag ) { + i += n; +} + +/** + * \brief A generalization of pointer arithmetic. + * \param i A bidirectional iterator. + * \param n The \a delta by which to change \p i. + * + * This decrements \p i by \p n. For bidirectional and random access + * iterators, \p n may be negative, in which case \p i is incremented. + * + * For random access iterators, this uses their \c + and \c - operations + * and are constant time. For other %iterator classes they are linear time. + */ +template < typename BidirectionalIterator, typename Distance > +inline constexpr void retract ( BidirectionalIterator & i, Distance n ) { + typename std::iterator_traits < BidirectionalIterator >::difference_type d = n; + retractInternal ( i, d, std::__iterator_category ( i ) ); +} + } /* namespace ext */ #endif /* __ITERATOR_HPP_ */