Spec-Zone.ru › C++

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

Возвращаемое значение

1) Предшественник i.
2) Предшественник итератора i на n позиций.
3) Предшественник итератора i на n позиций или первый итератор, сравнивающийся равным bound, в зависимости от того, что встретится раньше.

Сложность

1) Константная.
2,3) Константная, если 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

См. также

ranges::next
(C++20)
увеличивает итератор на заданное расстояние или перемещает его к заданной границе
(функциональный объект алгоритма)
ranges::advance
(C++20)
перемещает итератор на заданное расстояние или к заданной границе
(функциональный объект алгоритма)
prev
(C++11)
уменьшает значение итератора
(шаблон функции)

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/iterator/ranges/prev

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API