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)
сдвигает итератор на заданное расстояние или до заданной границы
(niebloid)

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

Spec-Zone.ru

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