std::ranges::prev
Определён в заголовочном файле <iterator> | ||
|---|---|---|
| Сигнатура вызова | ||
template< std::bidirectional_iterator I > constexpr I prev( I i ); | (1) | (начиная с C++20) |
template< std::bidirectional_iterator I > constexpr I prev( I i, std::iter_difference_t<I> n ); | (2) | (начиная с C++20) |
template< std::bidirectional_iterator I > constexpr I prev( I i, std::iter_difference_t<I> n, I bound ); | (3) | (начиная с C++20) |
Возвращает предшественника итератора i на n позиций.
Описанные на этой странице функциональные объекты — это функциональные объекты алгоритмов (неофициально называемые niebloids), то есть:
- При вызове любого из них нельзя указывать явный список аргументов шаблона.
- Ни один из них не виден для поиска, зависящего от аргументов.
- Если любой из них найден при обычном неквалифицированном поиске как имя слева от оператора вызова функции, поиск, зависящий от аргументов блокируется.
Параметры
| i | - | итератор |
| n | - | число элементов, на которое следует перейти назад i |
| bound | - | итератор, обозначающий начало диапазона, на который указывает i |
Возвращаемое значение
i.i на n позиций.i на n позиций или первый итератор, сравнивающийся равным bound, в зависимости от того, что встретится раньше.Сложность
I соответствует концепту std::random_access_iterator<I>; в противном случае линейная.Возможная реализация
struct prev_fn
{
template<std::bidirectional_iterator I>
constexpr I operator()(I i) const
{
--i;
return i;
}
template<std::bidirectional_iterator I>
constexpr I operator()(I i, std::iter_difference_t<I> n) const
{
ranges::advance(i, -n);
return i;
}
template<std::bidirectional_iterator I>
constexpr I operator()(I i, std::iter_difference_t<I> n, I bound) const
{
ranges::advance(i, -n, bound);
return i;
}
};
inline constexpr auto prev = prev_fn();
|
Примечания
Хотя выражение --r.end() часто компилируется для контейнеров, это не гарантируется: r.end() является выражением rvalue, и требования к итераторам не гарантируют, что декремент rvalue будет работать. В частности, если итераторы реализованы как указатели или operator-- квалифицировано как lvalue-ссылка, --r.end() не компилируется, тогда как ranges::prev(r.end()) компилируется.
Ситуация усугубляется для диапазонов, не соответствующих концепту ranges::common_range. Например, для некоторых базовых диапазонов ranges::transform_view::end имеет тип возвращаемого значения, отличный от ranges::transform_view::begin, поэтому --r.end() не компилируется. Это нельзя исправить с помощью ranges::prev, однако существуют обходные решения.
Пример
#include <iostream>
#include <iterator>
#include <vector>
int main()
{
std::vector<int> v{3, 1, 4};
auto pv = std::ranges::prev(v.end(), 2);
std::cout << *pv << '\n';
pv = std::ranges::prev(pv, 42, v.begin());
std::cout << *pv << '\n';
}
Вывод:
1 3
См. также
|
(C++20) | увеличивает итератор на заданное расстояние или перемещает его к заданной границе (функциональный объект алгоритма) |
|
(C++20) | перемещает итератор на заданное расстояние или к заданной границе (функциональный объект алгоритма) |
|
(C++11) | уменьшает значение итератора (шаблон функции) |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator/ranges/prev