Namespaces
Variants

std:: advance

From cppreference.net
Iterator library
Iterator concepts
Iterator primitives
Algorithm concepts and utilities
Indirect callable concepts
Common algorithm requirements
(C++20)
(C++20)
(C++20)
Utilities
(C++20)
Iterator adaptors
Range access
(C++11) (C++14)
(C++14) (C++14)
(C++11) (C++14)
(C++14) (C++14)
(C++17) (C++20)
(C++17)
(C++17)
Определено в заголовке <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

Смотрите также

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