Skip to main content

std::reverse() algorithm

// (1)
template< class InputIt, class OutputIt, class UnaryOperation >
constexpr OutputIt transform( InputIt first1, InputIt last1,
OutputIt d_first, UnaryOperation unary_op );

// (2)
template< class InputIt1, class InputIt2,
class OutputIt, class BinaryOperation >
constexpr OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2,
OutputIt d_first, BinaryOperation binary_op );

// (3)
template< class ExecutionPolicy, class ForwardIt1,
class ForwardIt2, class UnaryOperation >
ForwardIt2 transform( ExecutionPolicy&& policy,
ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 d_first, UnaryOperation unary_op );

// (4)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
class ForwardIt3, class BinaryOperation >
ForwardIt3 transform( ExecutionPolicy&& policy,
ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
ForwardIt3 d_first, BinaryOperation binary_op );

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.

  • (3, 4) Same as (1) and (2), but executed according to policy.

    Overload Resolution

    These overloads participate in overload resolution only if std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true.  (until C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true.  (since C++20)

Parameters

first
second

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

policy

The execution policy to use. See execution policy for details.

Type requirements

BidirItValueSwappable
LegacyBidirectionalIterator

Return value

(none)

Complexity

Exactly (last - first) / 2 swaps.

Exceptions

The overloads with a template parameter named ExecutionPolicy report errors as follows:

  • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For any other ExecutionPolicy, the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

Possible implementation

reverse(1)
template<class BidirIt>
constexpr // since C++20
void reverse(BidirIt first, BidirIt last)
{
using iter_cat = typename std::iterator_traits<BidirIt>::iterator_category;

// Tag dispatch, e.g. calling reverse_impl(first, last, iter_cat()),
// can be used in C++14 and earlier modes.
if constexpr (std::is_base_of_v<std::random_access_iterator_tag, iter_cat>)
{
if (first == last)
return;

for (--last; first < last; (void)++first, --last)
std::iter_swap(first, last);
}
else
while (first != last && first != --last)
std::iter_swap(first++, last);
}

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 <iostream>
#include <iterator>
#include <vector>

void println(auto rem, auto const& v)
{
for (std::cout << rem; auto e : v)
std::cout << e << ' ';
std::cout << '\n';
}

int main()
{
std::vector<int> v {1, 2, 3};
std::reverse(v.begin(), v.end());
println("after reverse, v = ", v);

int a[] = {4, 5, 6, 7};
std::reverse(std::begin(a), std::end(a));
println("after reverse, a = ", a);
}
Output
after reverse, v = 3 2 1
after reverse, a = 7 6 5 4
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::reverse() algorithm

// (1)
template< class InputIt, class OutputIt, class UnaryOperation >
constexpr OutputIt transform( InputIt first1, InputIt last1,
OutputIt d_first, UnaryOperation unary_op );

// (2)
template< class InputIt1, class InputIt2,
class OutputIt, class BinaryOperation >
constexpr OutputIt transform( InputIt1 first1, InputIt1 last1, InputIt2 first2,
OutputIt d_first, BinaryOperation binary_op );

// (3)
template< class ExecutionPolicy, class ForwardIt1,
class ForwardIt2, class UnaryOperation >
ForwardIt2 transform( ExecutionPolicy&& policy,
ForwardIt1 first1, ForwardIt1 last1,
ForwardIt2 d_first, UnaryOperation unary_op );

// (4)
template< class ExecutionPolicy, class ForwardIt1, class ForwardIt2,
class ForwardIt3, class BinaryOperation >
ForwardIt3 transform( ExecutionPolicy&& policy,
ForwardIt1 first1, ForwardIt1 last1, ForwardIt2 first2,
ForwardIt3 d_first, BinaryOperation binary_op );

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.

  • (3, 4) Same as (1) and (2), but executed according to policy.

    Overload Resolution

    These overloads participate in overload resolution only if std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> is true.  (until C++20) std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> is true.  (since C++20)

Parameters

first
second

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

policy

The execution policy to use. See execution policy for details.

Type requirements

BidirItValueSwappable
LegacyBidirectionalIterator

Return value

(none)

Complexity

Exactly (last - first) / 2 swaps.

Exceptions

The overloads with a template parameter named ExecutionPolicy report errors as follows:

  • If execution of a function invoked as part of the algorithm throws an exception and ExecutionPolicy is one of the standard policies, std::terminate is called. For any other ExecutionPolicy, the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

Possible implementation

reverse(1)
template<class BidirIt>
constexpr // since C++20
void reverse(BidirIt first, BidirIt last)
{
using iter_cat = typename std::iterator_traits<BidirIt>::iterator_category;

// Tag dispatch, e.g. calling reverse_impl(first, last, iter_cat()),
// can be used in C++14 and earlier modes.
if constexpr (std::is_base_of_v<std::random_access_iterator_tag, iter_cat>)
{
if (first == last)
return;

for (--last; first < last; (void)++first, --last)
std::iter_swap(first, last);
}
else
while (first != last && first != --last)
std::iter_swap(first++, last);
}

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 <iostream>
#include <iterator>
#include <vector>

void println(auto rem, auto const& v)
{
for (std::cout << rem; auto e : v)
std::cout << e << ' ';
std::cout << '\n';
}

int main()
{
std::vector<int> v {1, 2, 3};
std::reverse(v.begin(), v.end());
println("after reverse, v = ", v);

int a[] = {4, 5, 6, 7};
std::reverse(std::begin(a), std::end(a));
println("after reverse, a = ", a);
}
Output
after reverse, v = 3 2 1
after reverse, a = 7 6 5 4
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.