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) |
Если
n
отрицательно, итератор декрементируется. В этом случае
I
должен моделировать
std::bidirectional_iterator
, и
S
должен быть того же типа, что и
I
, если указан
bound
, иначе поведение не определено.
Описываемые на этой странице функциональные сущности являются algorithm function objects (неформально известными как niebloids ), то есть:
- Явные списки аргументов шаблона не могут быть указаны при вызове любого из них.
- Ни один из них не видим для argument-dependent lookup .
- Когда любой из них найден с помощью normal unqualified lookup как имя слева от оператора вызова функции, argument-dependent lookup блокируется.
Содержание |
Параметры
| i | - | итератор для продвижения |
| bound | - | ограничитель, обозначающий конец диапазона 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 не является constexpr до 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) значение: " << *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) значение: " << *vi << '\n'; std::cout << "4) разница: " << std::ranges::advance(vi, 2, v.end()) << ", значение: " << *vi << '\n'; std::cout << "5) разница: " << 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)
|
возвращает расстояние между итератором и стражем, или между началом и концом диапазона
(функциональный объект алгоритма) |
|
перемещает итератор на заданное расстояние
(шаблон функции) |