# std::advance

< cpp‎ | iterator

定义于头文件 `<iterator>` |  |
template< class InputIt, class Distance > void advance( InputIt& it, Distance n ); |  | (C++17 前)
template< class InputIt, class Distance > constexpr void advance( InputIt& it, Distance n ); |  | (C++17 起)

增加给定的迭代器 `it` 以 `n` 个元素的步长。

若 `n` 为负，则迭代器自减。该情况下， `InputIt` 必须满足老式双向迭代器 (LegacyBidirectionalIterator) 的要求，否则行为未定义。

### 参数

it | - | 要前进的迭代器
n | - | `it` 要前进的元素数
类型要求
- `InputIt` 必须满足老式输入迭代器 (LegacyInputIterator) 的要求。

### 返回值

（无）

### 复杂度

线性。

然而，若 `InputIt` 额外满足老式随机访问迭代器 (LegacyRandomAccessIterator) 的要求，则复杂度是常数。

### 注解

若指定的自增或自减序列要求一个不可自增迭代器（例如尾后迭代器）自增，或不可自减迭代器（例如首迭代器或孤立迭代器）自减，则行为未定义。

### 可能的实现

参阅 libstdc++ 与 libc++ 中的实现。

版本一
    // 经由标签派发的实现，移除 constexpr 后可用于 C++98
    namespace detail {

    template<class It>
    constexpr // 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 // 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 // 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 // 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());
    }
版本二
    // 经由 constexpr if 的实现，可用于 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;
                }
            }
        }
    }

### 示例

    #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';
    }

输出：

    4

### 参阅

next (C++11) | 令迭代器自增 (函数模板)
distance | 返回两个迭代器间的距离 (函数模板)