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
См. также
|
(C++11) | увеличивает итератор (шаблон функции) |
|
(C++11) | уменьшает итератор (шаблон функции) |
| возвращает расстояние между двумя итераторами (шаблон функции) |
|
|
(C++20) | перемещает итератор на заданное расстояние или до заданной границы (объект-функция алгоритма) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator/advance