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 предоставлен, в противном случае поведение не определено.
Функциональные сущности, описанные на этой странице, являются неблоидами, то есть:
- Явные списки шаблонных аргументов не могут быть указаны при вызове любого из них.
- Ни один из них не виден для поиска аргументов, зависящих от контекста.
- Когда любой из них найден обычным поиском без квалификатора в качестве имени слева от оператора вызова функции, поиск аргументов, зависящих от контекста, запрещён.
На практике они могут быть реализованы как объекты функций или с помощью специальных расширений компилятора.
Параметры
| 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/w/cpp/iterator/ranges/advance