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) |
Возвращает nй предшественник итератора i.
Функциональные сущности, описанные на этой странице, являются ниблеоидами, то есть:
- Явные списки аргументов шаблона нельзя указывать при их вызове.
- Ни один из них не виден для поиска аргументов, зависящих от контекста.
- Если при обычном безусловном поиске имя слева от оператора вызова функции соответствует одному из них, поиск аргументов, зависящих от контекста блокируется.
На практике они могут быть реализованы как объекты-функции или с помощью специальных расширений компилятора.
Параметры
| i | - | итератор |
| n | - | количество элементов, на которое необходимо вернуться назад от итератора i |
| bound | - | итератор, обозначающий начало диапазона, к которому относится i |
Возвращаемое значение
i.nй предшественник итератора i.nй предшественник итератора i, или первый итератор, равный bound, в зависимости от того, что будет достигнуто раньше.Сложность
Возможная реализация
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() является выражением-ссылкой-на-нечто-кратковременное, и нет требований к итераторам, гарантирующим работу декремента с таким выражением. В частности, когда итераторы реализуются как указатели или их 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/w/cpp/iterator/ranges/prev