std::ranges::views::reverse, std::ranges::reverse_view

< cpp‎ | ranges
Defined in header <ranges>
template< ranges::view V >

    requires ranges::bidirectional_range<V>

class reverse_view : public ranges::view_interface<reverse_view<V>>
(1) (since C++20)
namespace views {

    inline constexpr /*unspecified*/ reverse = /*unspecified*/;

(2) (since C++20)
1) A range adaptor that represents a view of underlying view with reversed order.
2) The expression views::reverse(E) is expression-equivalent to one of the following expressions, except that E is evaluated only once:
  • E.base(), if the type of E is a (possibly cv-qualified) specialization of reverse_view;
  • otherwise, if the type of E is (possibly cv-qualified) ranges::subrange<std::reverse_iterator<I>, std::reverse_iterator<I>, K> for some iterator type I and value K of type ranges::subrange_kind:
  • ranges::subrange<I, I, K>(E.end().base(), E.begin().base(), E.size()), if K is ranges::subrange_kind::sized;
  • otherwise ranges::subrange<I, I, K>(E.end().base(), E.begin().base());
  • otherwise ranges::reverse_view{E}.
In other words, views::reverse unwraps reversed views if possible.


[edit] Expression-equivalent

Expression e is expression-equivalent to expression f, if e and f have the same effects, either are both potentially-throwing or are both not potentially-throwing (i.e. noexcept(e) == noexcept(f)), and either are both constant subexpressions or are both not constant subexpressions.

[edit] Data members


V base_ = V(); /* exposition-only */

the underlying view

[edit] Member functions

constructs a reverse_view
(public member function)
returns the underlying view V
(public member function)
returns the beginning iterator of the reverse_view
(public member function)
returns the sentinel of the reverse_view
(public member function)
returns the size of the view if it is bounded
(public member function)
Inherited from std::ranges::view_interface
Returns whether the derived view is empty. Provided if it satisfies forward_range.
(public member function of std::ranges::view_interface<D>) [edit]
Returns whether the derived view is not empty. Provided if ranges::empty is applicable to it.
(public member function of std::ranges::view_interface<D>) [edit]
Returns the first element in the derived view. Provided if it satisfies forward_range.
(public member function of std::ranges::view_interface<D>) [edit]
Returns the last element in the derived view. Provided if it satisfies bidirectional_range and common_range.
(public member function of std::ranges::view_interface<D>) [edit]
Returns the nth element in the derived view. Provided if it satisfies random_access_range.
(public member function of std::ranges::view_interface<D>) [edit]


reverse_view() = default;
constexpr reverse_view(V base);
template<ranges::viewable_range R>

        ranges::bidirectional_range<R> &&
        std::constructible_from<V, views::all_t<R>>

constexpr reverse_view(R&& r);
1) Value-initializes base_
2) Initializes base_ with std::move(base).
3) Initializes base_ with views::all(std::forward<R>(r)).


r - range to reverse


constexpr V base() const;

Equivalent to return base_;


constexpr std::reverse_iterator<ranges::iterator_t<V>> begin()
  requires ranges::common_range<V>;
constexpr std::reverse_iterator<ranges::iterator_t<const V>> begin() const
  requires ranges::common_range<const V>;
1) Returns std::make_reverse_iterator(ranges::next(ranges::begin(base_), ranges::end(base_))). In order to provide the amortized constant time complexity required by the range concept, this function caches the result within the reverse_view object for use on subsequent calls.
2) Equivalent to return std::make_reverse_iterator(ranges::end(base_));.


constexpr std::reverse_iterator<ranges::iterator_t<const V>> end() const
  requires ranges::common_range<const V>;

Equivalent to return std::make_reverse_iterator(ranges::begin(base_));.


constexpr auto size() requires ranges::sized_range<V> {

    return ranges::size(base_);

constexpr auto size() const requires ranges::sized_range<const V> {

    return ranges::size(base_);


Returns the size of the view if the view is bounded.

[edit] Deduction guides

template<class R>
reverse_view(R&&) -> reverse_view<views::all_t<R>>;

[edit] Helper templates

template<class T>

inline constexpr bool enable_borrowed_range<std::ranges::reverse_view<T>> =

(since C++20)

This specialization of std::ranges::enable_borrowed_range makes reverse_view satisfy borrowed_range when the underlying view satisfies it.

[edit] Example

#include <ranges>
#include <iostream>
int main()
    static constexpr auto il = {3, 1, 4, 1, 5, 9};
    std::ranges::reverse_view rv {il};
    for (int i : rv)
        std::cout << i << ' ';
    std::cout << '\n';
    for (int i : il | std::views::reverse)
        std::cout << i << ' ';
    std::cout << '\n';
    // operator[] is inherited from `view_interface`
    for (auto i{0U}; i != rv.size(); ++i)
        std::cout << rv[i] << ' ';
    std::cout << '\n';


9 5 1 4 1 3
9 5 1 4 1 3
9 5 1 4 1 3

[edit] Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
LWG 3494 C++20 reverse_view was never a borrowed_range it is a borrowed_range if its underlying view is

[edit] See also

iterator adaptor for reverse-order traversal
(class template) [edit]
reverses the order of elements in a range
(niebloid) [edit]
creates a copy of a range that is reversed
(niebloid) [edit]