std::ranges::advance
Определён в заголовочном файле <iterator> | ||
|---|---|---|
| Сигнатура вызова | ||
template< std::input_or_output_iterator I > constexpr void advance( I& i, std::iter_difference_t<I> n ); | (1) | (начиная с C++20) |
template< std::input_or_output_iterator I, std::sentinel_for<I> S > constexpr void advance( I& i, S bound ); | (2) | (начиная с C++20) |
template< std::input_or_output_iterator I, std::sentinel_for<I> S > constexpr std::iter_difference_t<I> advance( I& i, std::iter_difference_t<I> n, S bound ); | (3) | (начиная с C++20) |
i на n раз.i до i == bound.i на n раз или до i == bound — в зависимости от того, что наступит раньше.Если n отрицательно, итератор уменьшается. В этом случае I должен соответствовать требованиям std::bidirectional_iterator, а S должен иметь тот же тип, что и I, если задан bound; в противном случае поведение не определено.
Описанные на этой странице функциональные сущности являются объектами-функциями алгоритмов (неформально известными как niebloids
- При вызове любой из них нельзя указывать явный список аргументов шаблона.
- Ни одна из них не видна при поиске, зависящем от аргументов.
- Если какая-либо из них найдена посредством обычного неквалифицированного поиска как имя слева от оператора вызова функции, поиск, зависящий от аргументов подавляется.
Параметры
| i | - | итератор, который нужно переместить |
| bound | - | сентинел, обозначающий конец диапазона, i является итератором к |
| n | - | максимальное число увеличений i |
Возвращаемое значение
n и фактически пройденным расстоянием i.Сложность
Линейная.
Однако если I дополнительно соответствует требованиям std::random_access_iterator, или S соответствует требованиям std::sized_sentinel_for<I>, или I и S соответствуют требованиям std::assignable_from<I&, S>, сложность постоянная.
Примечания
Поведение не определено, если указанная последовательность увеличений или уменьшений требует увеличить итератор, который нельзя увеличить (например, итератор за концом диапазона), или уменьшить итератор, который нельзя уменьшить (например, итератор на первом элементе или сингулярный итератор).
Возможная реализация
struct advance_fn
{
template<std::input_or_output_iterator I>
constexpr void operator()(I& i, std::iter_difference_t<I> n) const
{
if constexpr (std::random_access_iterator<I>)
i += n;
else
{
while (n > 0)
{
--n;
++i;
}
if constexpr (std::bidirectional_iterator<I>)
{
while (n < 0)
{
++n;
--i;
}
}
}
}
template<std::input_or_output_iterator I, std::sentinel_for<I> S>
constexpr void operator()(I& i, S bound) const
{
if constexpr (std::assignable_from<I&, S>)
i = std::move(bound);
else if constexpr (std::sized_sentinel_for<S, I>)
(*this)(i, bound - i);
else
while (i != bound)
++i;
}
template<std::input_or_output_iterator I, std::sentinel_for<I> S>
constexpr std::iter_difference_t<I>
operator()(I& i, std::iter_difference_t<I> n, S bound) const
{
if constexpr (std::sized_sentinel_for<S, I>)
{
// std::abs is not constexpr until C++23
auto abs = [](const std::iter_difference_t<I> x) { return x < 0 ? -x : x; };
if (const auto dist = abs(n) - abs(bound - i); dist < 0)
{
(*this)(i, bound);
return -dist;
}
(*this)(i, n);
return 0;
}
else
{
while (n > 0 && i != bound)
{
--n;
++i;
}
if constexpr (std::bidirectional_iterator<I>)
{
while (n < 0 && i != bound)
{
++n;
--i;
}
}
return n;
}
}
};
inline constexpr auto advance = advance_fn();
|
Пример
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> v {3, 1, 4};
auto vi = v.begin();
std::ranges::advance(vi, 2);
std::cout << "1) value: " << *vi << '\n' << std::boolalpha;
std::ranges::advance(vi, v.end());
std::cout << "2) vi == v.end(): " << (vi == v.end()) << '\n';
std::ranges::advance(vi, -3);
std::cout << "3) value: " << *vi << '\n';
std::cout << "4) diff: " << std::ranges::advance(vi, 2, v.end())
<< ", value: " << *vi << '\n';
std::cout << "5) diff: " << std::ranges::advance(vi, 4, v.end())
<< ", vi == v.end(): " << (vi == v.end()) << '\n';
}
Вывод:
1) value: 4 2) vi == v.end(): true 3) value: 3 4) diff: 0, value: 4 5) diff: 3, vi == v.end(): true
См. также
|
(C++20) | увеличивает итератор на заданное расстояние или перемещает его до заданной границы (объект-функция алгоритма) |
|
(C++20) | уменьшает итератор на заданное расстояние или перемещает его до заданной границы (объект-функция алгоритма) |
|
(C++20) | возвращает расстояние между итератором и сентинелом либо между началом и концом диапазона (объект-функция алгоритма) |
| перемещает итератор на заданное расстояние (шаблон функции) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator/ranges/advance