std::reverse_iterator(3)

NAME
std::reverse_iterator - std::reverse_iterator

Synopsis
   Defined in header <iterator>
   template< class Iter >
   class reverse_iterator;
   std::reverse_iterator is an iterator adaptor that reverses the direction of a given
   iterator, which must be at least a LegacyBidirectionalIterator
   or model bidirectional_iterator
   (since C++20). In other words, when provided with a bidirectional iterator,
   std::reverse_iterator produces a new iterator that moves from the end to the
   beginning of the sequence defined by the underlying bidirectional iterator.
   For a reverse iterator r constructed from an iterator i, the relationship &*r ==
   &*(i - 1) is always true (as long as r is dereferenceable); thus a reverse iterator
   constructed from a one-past-the-end iterator dereferences to the last element in a
   sequence.
   This is the iterator returned by member functions rbegin() and rend() of the
   standard library containers.
   range-rbegin-rend.svg

Member types
   Member type Definition
   iterator_type Iter
   iterator_category std::iterator_traits<Iter>::iterator_category (until
   value_type std::iterator_traits<Iter>::value_type C++20)
   difference_type std::iterator_traits<Iter>::difference_type
   pointer std::iterator_traits<Iter>::pointer
   reference std::iterator_traits<Iter>::reference
   Member type Definition
   iterator_type Iter
                     If Iter models std::random_access_iterator, this is
   iterator_concept std::random_access_iterator_tag. Otherwise, this is
                     std::bidirectional_iterator_tag
                     If std::iterator_traits<Iter>::iterator_category models (since
   iterator_category std::derived_from<std::random_access_iterator_tag>, this is C++20)
                     std::random_access_iterator_tag. Otherwise, this is
                     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>
   Member types iterator_category, value_type, difference_type, pointer
   and reference are required to be obtained by inheriting from
   std::iterator<
       std::iterator_traits<Iter>::iterator_category,
       std::iterator_traits<Iter>::value_type, (until C++17)
       std::iterator_traits<Iter>::difference_type,
       std::iterator_traits<Iter>::pointer,
       std::iterator_traits<Iter>::reference
   >.

Member functions
   constructor constructs a new iterator adaptor
                   (public member function)
   operator= assigns another iterator adaptor
                   (public member function)
   base accesses the underlying iterator
                   (public member function)
   operator* accesses the pointed-to element
   operator-> (public member function)
   operator[] accesses an element by index
                   (public member function)
   operator++
   operator++(int)
   operator+=
   operator+ advances or decrements the iterator
   operator-- (public member function)
   operator--(int)
   operator-=
   operator-

Member objects
   Member name Definition
   current (protected) the underlying iterator of which base() returns a copy

Non-member functions
   operator==
   operator!=
   operator<
   operator<= compares the underlying iterators
   operator> (function template)
   operator>=
   operator<=>
   (C++20)
   operator+ advances the iterator
                        (function template)
   operator- computes the distance between two iterator adaptors
                        (function template)
   iter_move casts the result of dereferencing the adjusted underlying
   (C++20) iterator to its associated rvalue reference type
                        (function)
   iter_swap swaps the objects pointed to by two adjusted underlying
   (C++20) iterators
                        (function template)
   make_reverse_iterator creates a std::reverse_iterator of type inferred from the
   (C++14) argument
                        (function template)
   Helper templates
   template< class Iterator1, class Iterator2 >
       requires (!std::sized_sentinel_for<Iterator1, Iterator2>)
   inline constexpr bool disable_sized_sentinel_for< (since C++20)
       std::reverse_iterator<Iterator1>,
       std::reverse_iterator<Iterator2>> = true;
   This partial specialization of std::disable_sized_sentinel_for prevents
   specializations of reverse_iterator from satisfying sized_sentinel_for if their
   underlying iterators do not satisfy the concept.

Possible implementation
   Below is a partial implementation focusing on the way the inner iterator is stored,
   calling std::prev only when the content is fetched via operator*. 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. };

Notes
   std::reverse_iterator does not work with iterators whose dereference returns a
   reference to a member of *this (so-called "stashing iterators"). An example of a
   stashing iterator is MSVC STL's std::filesystem::path::iterator.

Example
// Run this code
 #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';
 }

Output:
 35 25 15 5

See also
   make_reverse_iterator creates a std::reverse_iterator of type inferred from the
   (C++14) argument
                        (function template)
   iterator base class to ease the definition of required types for simple
   (deprecated in C++17) iterators
                        (class template)