Skip to main content

std::rotate() algorithm

// (1)
template< class ForwardIt >
constexpr ForwardIt rotate( ForwardIt first, ForwardIt middle, ForwardIt last );

// (2)
template< class ExecutionPolicy, class ForwardIt >
ForwardIt rotate( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt middle, ForwardIt last );
  • (1) Performs a left rotation on a range of elements.

    Specifically, swaps the elements in the range [first; last) in such a way that the elements in [first; middle) are placed after the elements in [middle; last) while the orders of the elements in both ranges are preserved.

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

    Overload Resolution

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

Undefined Behaviour

If [first; middle) or [middle; last) is not a valid range, the behavior is undefined.

Parameters

first

The beginning of the original range.

middle

Iterator to the element that should appear at the beginning of the rotated range.

last

The end of the original range.

policy

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

Type requirements

ForwardItLegacyForwardIterator
ValueSwappable
*first
*middle
last
MoveAssignable
MoveConstructible

Return value

An iterator that is equal to:

  • last, if first == middle
  • first, if middle == last
  • first + (last - middle) otherwise (the new location of the element pointed by first)
    (the + and - operations are not required to be supported, they are only used to represent to position of the returned iterator).

Complexity

Linear in the distance between first and last.

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

rotate (1)
template<class ForwardIt>
constexpr // since C++20
ForwardIt rotate(ForwardIt first, ForwardIt middle, ForwardIt last)
{
if (first == middle)
return last;

if (middle == last)
return first;

ForwardIt write = first;
ForwardIt next_read = first; // read position for when "read" hits "last"

for (ForwardIt read = middle; read != last; ++write, ++read)
{
if (write == next_read)
next_read = read; // track where "first" went
std::iter_swap(write, read);
}

// rotate the remaining sequence into place
rotate(write, next_read, last);
return write;
}

Notes

std::rotate has better efficiency on common implementations if ForwardIt satisfies LegacyBidirectionalIterator or (better) LegacyRandomAccessIterator.

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

Examples

std::rotate is a common building block in many algorithms. This example demonstrates insertion sort.

Main.cpp
#include <algorithm>
#include <iostream>
#include <vector>

auto print = [](auto const remark, auto const& v)
{
std::cout << remark;
for (auto n : v)
std::cout << n << ' ';
std::cout << '\n';
};

int main()
{
std::vector<int> v {2, 4, 2, 0, 5, 10, 7, 3, 7, 1};
print("before sort:\t\t", v);

// insertion sort
for (auto i = v.begin(); i != v.end(); ++i)
std::rotate(std::upper_bound(v.begin(), i, *i), i, i + 1);
print("after sort:\t\t", v);

// simple rotation to the left
std::rotate(v.begin(), v.begin() + 1, v.end());
print("simple rotate left:\t", v);

// simple rotation to the right
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend());
print("simple rotate right:\t", v);
}
Output
before sort:		2 4 2 0 5 10 7 3 7 1
after sort: 0 1 2 2 3 4 5 7 7 10
simple rotate left: 1 2 2 3 4 5 7 7 10 0
simple rotate right: 0 1 2 2 3 4 5 7 7 10
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::rotate() algorithm

// (1)
template< class ForwardIt >
constexpr ForwardIt rotate( ForwardIt first, ForwardIt middle, ForwardIt last );

// (2)
template< class ExecutionPolicy, class ForwardIt >
ForwardIt rotate( ExecutionPolicy&& policy,
ForwardIt first, ForwardIt middle, ForwardIt last );
  • (1) Performs a left rotation on a range of elements.

    Specifically, swaps the elements in the range [first; last) in such a way that the elements in [first; middle) are placed after the elements in [middle; last) while the orders of the elements in both ranges are preserved.

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

    Overload Resolution

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

Undefined Behaviour

If [first; middle) or [middle; last) is not a valid range, the behavior is undefined.

Parameters

first

The beginning of the original range.

middle

Iterator to the element that should appear at the beginning of the rotated range.

last

The end of the original range.

policy

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

Type requirements

ForwardItLegacyForwardIterator
ValueSwappable
*first
*middle
last
MoveAssignable
MoveConstructible

Return value

An iterator that is equal to:

  • last, if first == middle
  • first, if middle == last
  • first + (last - middle) otherwise (the new location of the element pointed by first)
    (the + and - operations are not required to be supported, they are only used to represent to position of the returned iterator).

Complexity

Linear in the distance between first and last.

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

rotate (1)
template<class ForwardIt>
constexpr // since C++20
ForwardIt rotate(ForwardIt first, ForwardIt middle, ForwardIt last)
{
if (first == middle)
return last;

if (middle == last)
return first;

ForwardIt write = first;
ForwardIt next_read = first; // read position for when "read" hits "last"

for (ForwardIt read = middle; read != last; ++write, ++read)
{
if (write == next_read)
next_read = read; // track where "first" went
std::iter_swap(write, read);
}

// rotate the remaining sequence into place
rotate(write, next_read, last);
return write;
}

Notes

std::rotate has better efficiency on common implementations if ForwardIt satisfies LegacyBidirectionalIterator or (better) LegacyRandomAccessIterator.

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

Examples

std::rotate is a common building block in many algorithms. This example demonstrates insertion sort.

Main.cpp
#include <algorithm>
#include <iostream>
#include <vector>

auto print = [](auto const remark, auto const& v)
{
std::cout << remark;
for (auto n : v)
std::cout << n << ' ';
std::cout << '\n';
};

int main()
{
std::vector<int> v {2, 4, 2, 0, 5, 10, 7, 3, 7, 1};
print("before sort:\t\t", v);

// insertion sort
for (auto i = v.begin(); i != v.end(); ++i)
std::rotate(std::upper_bound(v.begin(), i, *i), i, i + 1);
print("after sort:\t\t", v);

// simple rotation to the left
std::rotate(v.begin(), v.begin() + 1, v.end());
print("simple rotate left:\t", v);

// simple rotation to the right
std::rotate(v.rbegin(), v.rbegin() + 1, v.rend());
print("simple rotate right:\t", v);
}
Output
before sort:		2 4 2 0 5 10 7 3 7 1
after sort: 0 1 2 2 3 4 5 7 7 10
simple rotate left: 1 2 2 3 4 5 7 7 10 0
simple rotate right: 0 1 2 2 3 4 5 7 7 10
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.