Spec-Zone.ru › C++

std::advance

Определён в заголовочном файле <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
namespace detail
{
    template<class It>
    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>
    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>
    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>
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
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 << ' ';
    
    vi = v.end();
    std::advance(vi, -2);
    std::cout << *vi << '\n';
}

Вывод:

4 1

См. также

next
(C++11)
увеличивает итератор
(шаблон функции)
prev
(C++11)
уменьшает итератор
(шаблон функции)
distance
возвращает расстояние между двумя итераторами
(шаблон функции)
ranges::advance
(C++20)
перемещает итератор на заданное расстояние или до заданной границы
(объект-функция алгоритма)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator/advance

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API