// N4317 "New Safer Functions to Advance Iterators" paper can be found at // http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4317.pdf namespace detail { template inline void do_advance(InputIter& it, InputIter end, typename std::iterator_traits::difference_type n, std::input_iterator_tag) { assert(n >= 0); for (; (n > 0) && (it != end); --n) ++it; } template inline void do_advance(BiDirIter& it, BiDirIter end, typename std::iterator_traits::difference_type n, std::bidirectional_iterator_tag) { if (n >= 0) { for (; (n > 0) && (it != end); --n) ++it; } else { for (; (n < 0) && (it != end); ++n) --it; } } template inline void do_advance(RandIter& it, RandIter end, typename std::iterator_traits::difference_type n, std::random_access_iterator_tag) { it += std::min(n, end - it); } } template inline void advance(InputIter& it, InputIter end, typename std::iterator_traits::difference_type n) { detail::do_advance(it, end, n, typename std::iterator_traits::iterator_category{}); } template inline InputIter next(InputIter it, InputIter end, typename std::iterator_traits::difference_type n = 1) { advance(it, end, n); return it; } template inline BidirectionalIter prev(BidirectionalIter it, BidirectionalIter end, typename std::iterator_traits::difference_type n = 1) { static_assert(std::is_base_of::iterator_category>::value, "Bidirectional iterator required"); advance(it, end, -n); return it; }