Skip to main content

std::ranges::reverse() algorithm

// (1)
constexpr I reverse( I first, S last );

// (2)
constexpr ranges::borrowed_iterator_t<R> reverse( R&& r );

The type of arguments are generic and have following constraints:

  • I - std::bidirectional_iterator
  • S - std::sentinel_for<I>
  • R - ranges::bidirectional_range

Additionally, each overload has the following constraints:

  • (1) - std::permutable<I>
  • (2) - std::permutable<ranges::iterator_t<R>>

Reverses the order of elements.

  • (1) Reverses the order of the elements in the range [first; last).
    Behaves as if applying ranges::iter_swap to every pair of iterators first + i, last - i - 1 for each integer i, where 0 ≤ i < (last - first) / 2.

  • ** (2)** Same as (1), but uses r as the range, as if using ranges::begin(r) as first and ranges::end(r) as last.

The function-like entities described on this page are niebloids.

Parameters

first
last

The range of elements to reverse (iterator, sentinel pair).

r

The range of elements to reverse (ranges).

Return value

An iterator equal to last.

Complexity

Exactly (last - first) / 2 swaps.

Exceptions

(none)

Possible implementation

reverse(1) and reverse(2)
struct reverse_fn
{
template<std::bidirectional_iterator I, std::sentinel_for<I> S>
requires std::permutable<I>
constexpr I operator()(I first, S last) const
{
auto last2 {ranges::next(first, last)};
for (auto tail {last2}; !(first == tail or first == --tail); ++first)
ranges::iter_swap(first, tail);
return last2;
}

template<ranges::bidirectional_range R>
requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_iterator_t<R>
operator()(R&& r) const
{
return (*this)(ranges::begin(r), ranges::end(r));
}
};

inline constexpr reverse_fn reverse {};

Notes

Implementations (e.g. MSVC STL) may enable vectorization when the iterator type models contiguous_iterator and swapping its value type calls neither non-trivial special member function nor ADL-found swap.

Examples

Main.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <string>

int main()
{
std::string s {"ABCDEF"};
std::cout << s << " → ";
std::ranges::reverse(s.begin(), s.end());
std::cout << s << " → ";
std::ranges::reverse(s);
std::cout << s << " │ ";

std::array a {1, 2, 3, 4, 5};
for (auto e : a)
std::cout << e << ' ';
std::cout << "→ ";
std::ranges::reverse(a);
for (auto e : a)
std::cout << e << ' ';
std::cout << '\n';
}
Output
ABCDEF → FEDCBA → ABCDEF │ 1 2 3 4 5 → 5 4 3 2 1
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.

std::ranges::reverse() algorithm

// (1)
constexpr I reverse( I first, S last );

// (2)
constexpr ranges::borrowed_iterator_t<R> reverse( R&& r );

The type of arguments are generic and have following constraints:

  • I - std::bidirectional_iterator
  • S - std::sentinel_for<I>
  • R - ranges::bidirectional_range

Additionally, each overload has the following constraints:

  • (1) - std::permutable<I>
  • (2) - std::permutable<ranges::iterator_t<R>>

Reverses the order of elements.

  • (1) Reverses the order of the elements in the range [first; last).
    Behaves as if applying ranges::iter_swap to every pair of iterators first + i, last - i - 1 for each integer i, where 0 ≤ i < (last - first) / 2.

  • ** (2)** Same as (1), but uses r as the range, as if using ranges::begin(r) as first and ranges::end(r) as last.

The function-like entities described on this page are niebloids.

Parameters

first
last

The range of elements to reverse (iterator, sentinel pair).

r

The range of elements to reverse (ranges).

Return value

An iterator equal to last.

Complexity

Exactly (last - first) / 2 swaps.

Exceptions

(none)

Possible implementation

reverse(1) and reverse(2)
struct reverse_fn
{
template<std::bidirectional_iterator I, std::sentinel_for<I> S>
requires std::permutable<I>
constexpr I operator()(I first, S last) const
{
auto last2 {ranges::next(first, last)};
for (auto tail {last2}; !(first == tail or first == --tail); ++first)
ranges::iter_swap(first, tail);
return last2;
}

template<ranges::bidirectional_range R>
requires std::permutable<ranges::iterator_t<R>>
constexpr ranges::borrowed_iterator_t<R>
operator()(R&& r) const
{
return (*this)(ranges::begin(r), ranges::end(r));
}
};

inline constexpr reverse_fn reverse {};

Notes

Implementations (e.g. MSVC STL) may enable vectorization when the iterator type models contiguous_iterator and swapping its value type calls neither non-trivial special member function nor ADL-found swap.

Examples

Main.cpp
#include <algorithm>
#include <array>
#include <iostream>
#include <string>

int main()
{
std::string s {"ABCDEF"};
std::cout << s << " → ";
std::ranges::reverse(s.begin(), s.end());
std::cout << s << " → ";
std::ranges::reverse(s);
std::cout << s << " │ ";

std::array a {1, 2, 3, 4, 5};
for (auto e : a)
std::cout << e << ' ';
std::cout << "→ ";
std::ranges::reverse(a);
for (auto e : a)
std::cout << e << ' ';
std::cout << '\n';
}
Output
ABCDEF → FEDCBA → ABCDEF │ 1 2 3 4 5 → 5 4 3 2 1
This article originates from this CppReference page. It was likely altered for improvements or editors' preference. Click "Edit this page" to see all changes made to this document.
Hover to see the original license.