Namespaces
Variants
Views
Actions

std::advance

From cppreference.com
< cpp‎ | iterator
 
 
Iterator library
Iterator concepts
Iterator primitives
Iterator adaptors
Stream iterators
Iterator customization points
Iterator operations
advance
(C++11)
(C++11)
Range access
(C++11)(C++14)
(C++11)(C++14)
(C++17)(C++20)
(C++14)(C++14)
(C++14)(C++14)
(C++17)
(C++17)
 
Defined in header <iterator>
template< class InputIt, class Distance >
void advance( InputIt& it, Distance n );
(until C++17)
template< class InputIt, class Distance >
constexpr void advance( InputIt& it, Distance n );
(since C++17)

Increments given iterator it by n elements.

If n is negative, the iterator is decremented. In this case, InputIt must meet the requirements of LegacyBidirectionalIterator, otherwise the behavior is undefined.

Contents

[edit] Parameters

it - iterator to be advanced
n - number of elements it should be advanced
Type requirements
-
InputIt must meet the requirements of LegacyInputIterator.

[edit] Return value

(none)

[edit] Complexity

Linear.

However, if InputIt additionally meets the requirements of LegacyRandomAccessIterator, complexity is constant.

[edit] Notes

The behavior is undefined if the specified sequence of increments or decrements would require that a non-incrementable iterator (such as the past-the-end iterator) is incremented, or that a non-decrementable iterator (such as the front iterator or the singular iterator) is decremented.

[edit] Possible implementation

See also the implementations in libstdc++ and libc++.


First version
// implementation via tag dispatch, available in C++98 with constexpr removed
namespace detail {
 
template<class It>
constexpr // required since C++17
void do_advance(It& it, typename std::iterator_traits<It>::difference_type n,
                std::input_iterator_tag)
{
    while (n > 0) {
        --n;
        ++it;
    }
}
 
template<class It>
constexpr // required since C++17
void do_advance(It& it, typename std::iterator_traits<It>::difference_type n,
                std::bidirectional_iterator_tag)
{
    while (n > 0) {
        --n;
        ++it;
    }
    while (n < 0) {
        ++n;
        --it;
    }
}
 
template<class It>
constexpr // required since C++17
void do_advance(It& it, typename std::iterator_traits<It>::difference_type n,
                std::random_access_iterator_tag)
{
    it += n;
}
 
} // namespace detail
 
template<class It, class Distance>
constexpr // since C++17
void advance(It& it, Distance n)
{
    detail::do_advance(it, typename std::iterator_traits<It>::difference_type(n),
                       typename std::iterator_traits<It>::iterator_category());
}
Second version
// implementation via constexpr if, available in C++17
template<class It, class Distance>
constexpr void advance(It& it, Distance n)
{
    using category = typename std::iterator_traits<It>::iterator_category;
    static_assert(std::is_base_of_v<std::input_iterator_tag, category>);
 
    auto dist = typename std::iterator_traits<It>::difference_type(n);
    if constexpr (std::is_base_of_v<std::random_access_iterator_tag, category>)
        it += dist;
    else {
        while (dist > 0) {
            --dist;
            ++it;
        }
        if constexpr (std::is_base_of_v<std::bidirectional_iterator_tag, category>) {
            while (dist < 0) {
                ++dist;
                --it;
            }
        }
    }
}

[edit] Example

#include <iostream>
#include <iterator>
#include <vector>
 
int main() 
{
    std::vector<int> v{ 3, 1, 4 };
 
    auto vi = v.begin();
 
    std::advance(vi, 2);
 
    std::cout << *vi << '\n';
}

Output:

4

[edit] See also

(C++11)
increment an iterator
(function template) [edit]
returns the distance between two iterators
(function template) [edit]