Spec-Zone.ru › C++

std::reverse_iterator

Определено в заголовке <iterator>
template< class Iter >
class reverse_iterator;

std::reverse_iterator — это адаптер итераторов, который изменяет направление заданного итератора, который должен быть по крайней мере двунаправленным итератором или моделью bidirectional_iterator(с C++20). Другими словами, при использовании двунаправленного итератора, std::reverse_iterator создает новый итератор, который перемещается от конца к началу последовательности, определяемой базовым двунаправленным итератором.

Для обратного итератора r, созданного из итератора i, соотношение &*r == &*(i - 1) всегда true (пока r доступен для разыменования); таким образом, обратный итератор, созданный из итератора, указывающего на позицию после последнего элемента, разыменовывается в последний элемент последовательности.

Это итератор, возвращаемый функциями-членами rbegin() и rend() стандартных контейнеров библиотеки.

range-rbegin-rend.svg

Типы-члены

Тип-член Определение
iterator_type Iter
iterator_category std::iterator_traits<Iter>::iterator_category
value_type std::iterator_traits<Iter>::value_type
difference_type std::iterator_traits<Iter>::difference_type
pointer std::iterator_traits<Iter>::pointer
reference std::iterator_traits<Iter>::reference
(до C++20)
Тип-член Определение
iterator_type Iter
iterator_concept Если Iter моделирует std::random_access_iterator, это std::random_access_iterator_tag. В противном случае, это std::bidirectional_iterator_tag
iterator_category Если std::iterator_traits<Iter>::iterator_category моделирует std::derived_from<std::random_access_iterator_tag>, это std::random_access_iterator_tag. В противном случае, это std::iterator_traits<Iter>::iterator_category
value_type std::iter_value_t<Iter>
difference_type std::iter_difference_t<Iter>
pointer std::iterator_traits<Iter>::pointer
reference std::iter_reference_t<Iter>
(с C++20)

Типы-члены iterator_category, value_type, difference_type, pointer и reference должны быть получены посредством наследования от std::iterator<
std::iterator_traits<Iter>::iterator_category,
std::iterator_traits<Iter>::value_type,
std::iterator_traits<Iter>::difference_type,
std::iterator_traits<Iter>::pointer,
std::iterator_traits<Iter>::reference
>.

(до C++17)

Функции-члены

(конструктор)
создает новый адаптер итераторов
(общедоступная функция-член)
operator=
присваивает другой адаптер итераторов
(общедоступная функция-член)
base
получает доступ к базовому итератору
(общедоступная функция-член)
operator*operator->
получает доступ к элементу, на который указывает итератор
(общедоступная функция-член)
operator[]
получает доступ к элементу по индексу
(общедоступная функция-член)
operator++operator++(int)operator+=operator+operator--operator--(int)operator-=operator-
перемещает или уменьшает итератор
(общедоступная функция-член)

Объекты-члены

Имя объекта-члена Определение
current (защищен) базовый итератор, копия которого возвращается методом base()

Внешние функции

operator==operator!=operator<operator<=operator>operator>=operator<=>
(C++20)
сравнивает базовые итераторы
(шаблон функции)
operator+
продвигает итератор
(шаблон функции)
operator-
вычисляет расстояние между двумя итераторами-адаптерами
(шаблон функции)
iter_move
(C++20)
преобразует результат обращение к базовому итератору в ассоциированный тип ссылки rvalue
(функция)
iter_swap
(C++20)
меняет местами объекты, на которые указывают два изменённых базовых итератора
(шаблон функции)
make_reverse_iterator
(C++14)
создаёт std::reverse_iterator типа, определённого из аргумента
(шаблон функции)

Вспомогательные шаблоны

template< class Iterator1, class Iterator2 >
    requires (!std::sized_sentinel_for<Iterator1, Iterator2>)
inline constexpr bool disable_sized_sentinel_for<
    std::reverse_iterator<Iterator1>,
    std::reverse_iterator<Iterator2>> = true;
(с C++20)

Эта частичная специализация std::disable_sized_sentinel_for предотвращает специализации reverse_iterator от удовлетворения sized_sentinel_for, если их базовые итераторы не удовлетворяют концепции.

Возможная реализация

Ниже приведена частичная реализация, уделяющая внимание способу хранения внутреннего итератора, вызывающая std::prev только при извлечении содержимого через оператор *.

template<class It>
class reverse_iterator
{
protected:
    It current = It();
public:
    reverse_iterator() = default;
    constexpr explicit reverse_iterator(It itr) : current(itr) {}
    template<class U>
        requires (!std::is_same_v<U, It> && std::convertible_to<const U&, It>)
    constexpr explicit reverse_iterator(const U& other) : current(other.base()) {}
 
    constexpr decltype(auto) operator*() const
    {
        return *std::prev(current); // <== returns the content of prev
    }
 
    constexpr reverse_iterator& operator++() { --current; return *this; }
    constexpr reverse_iterator operator++(int) { auto tmp = *this; ++(*this); return tmp; }
 
    constexpr reverse_iterator& operator--() { ++current; return *this; }
    constexpr reverse_iterator operator--(int) { auto tmp = *this; --(*this); return tmp; }
 
    constexpr It base() const { return current; }
 
    // Other member functions, friend functions, and member typedefs are not shown here.
};

Примечания

std::reverse_iterator не работает с итераторами, чьё обращение возвращает ссылку на член *this (так называемые "итераторы-хранилища"). Примером итератора-хранилища является итератор MSVC STL std::filesystem::path::iterator.

Пример

#include <cstddef>
#include <iostream>
#include <iterator>
 
template<typename T, std::size_t SIZE>
class Stack
{
    T arr[SIZE];
    std::size_t pos = 0;
public:
    T pop()
    {
        return arr[--pos];
    }
 
    Stack& push(const T& t)
    {
        arr[pos++] = t;
        return *this;
    }
 
    // we wish that looping on Stack would be in LIFO order
    // thus we use std::reverse_iterator as an adaptor to existing iterators
    // (which are in this case the simple pointers: [arr, arr + pos)
    auto begin() { return std::reverse_iterator(arr + pos); }
    auto end() { return std::reverse_iterator(arr); }
};
 
int main()
{
    Stack<int, 8> s;
    s.push(5).push(15).push(25).push(35);
    for (int val : s)
        std::cout << val << ' ';
    std::cout << '\n';
}

Вывод:

35 25 15 5

См. также

make_reverse_iterator
(C++14)
создаёт std::reverse_iterator типа, определённого из аргумента
(шаблон функции)
iterator
(устарел в C++17)
базовый класс для упрощения определения требуемых типов для простых итераторов
(шаблон класса)

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

Spec-Zone.ru

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