Skip to main content

std::ranges::shift_right() algorithm

// (1)
constexpr ranges::subrange<I>
shift_right( I first, S last, std::iter_difference_t<I> n );

// (2)
constexpr ranges::borrowed_subrange_t<R>
shift_right( R&& r, ranges::range_difference_t<R> n );

The type of arguments are generic and have the following constraints:

  • I - std::permutable
  • S - std::sentinel_for<I>
  • R - std::ranges::forward_range

Additionally, each overload has the following constraints:

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

(The std:: namespace was ommitted here for readability)

Shifts the elements in the range [first; last) or r by n positions.

  • (1) Shifts the elements towards the end of the range:

    • If n == 0 || n >= last - first, there are no effects.
    • If n < 0, the behavior is undefined.
    • Otherwise, for every integer i in [0; last - first - n), moves the element originally at position first + i to position first + n + i.

    If I models bidirectional_iterator, then the moves are performed in decreasing order of i starting from last - first - n - 1.

  • ** (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.

Undefined Behaviour

The behavior is undefined

if [first; last) is not a valid range.

Parameters

first
last

The original range.

r

The range of elements to shift.

n

The number of positions to shift.

Return value

{
first,
/* NEW_LAST */
}

Where NEW_LAST is the end of the resulting range and equivalent to:

  • If n is less than last - first, first + n.
  • Otherwise, last.

Complexity

At most ranges::distance(first, last) - n assignments or swaps.

Exceptions

(none)

Notes

ranges::shift_right / ranges::shift_right has better efficiency on common implementations if I models bidirectional_iterator or random_access_iterator.

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 <string>
#include <type_traits>
#include <vector>

struct S
{
int value {0};
bool specified_state {true};

S(int v = 0) : value {v} {}
S(S const& rhs) = default;
S(S&& rhs) { *this = std::move(rhs); }
S& operator=(S const& rhs) = default;
S& operator=(S&& rhs)
{
if (this != &rhs)
{
value = rhs.value;
specified_state = rhs.specified_state;
rhs.specified_state = false;
}
return *this;
}
};

template<typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> const& v)
{
for (const auto& s : v)
{
if constexpr (std::is_same_v<T, S>)
s.specified_state ? os << s.value << ' ' : os << ". ";
else if constexpr (std::is_same_v<T, std::string>)
os << (s.empty() ? "." : s) << ' ';
else
os << s << ' ';
}
return os;
}

int main()
{
std::cout << std::left;

std::vector<S> a {1, 2, 3, 4, 5, 6, 7};
std::vector<int> b {1, 2, 3, 4, 5, 6, 7};
std::vector<std::string> c {"α", "β", "γ", "δ", "ε", "ζ", "η"};

std::cout << "vector<S> \tvector<int> \tvector<string>\n";
std::cout << a << " " << b << " " << c << '\n';

std::ranges::shift_left(a, 3);
std::ranges::shift_left(b, 3);
std::ranges::shift_left(c, 3);
std::cout << a << " " << b << " " << c << '\n';

std::ranges::shift_right(a, 2);
std::ranges::shift_right(b, 2);
std::ranges::shift_right(c, 2);
std::cout << a << " " << b << " " << c << '\n';

std::ranges::shift_left(a, 8); // has no effect: n >= last - first
std::ranges::shift_left(b, 8); // ditto
std::ranges::shift_left(c, 8); // ditto
std::cout << a << " " << b << " " << c << '\n';

// std::ranges::shift_left(a, -3); // UB
}
Output
vector<S>       vector<int>     vector<string>
1 2 3 4 5 6 7 1 2 3 4 5 6 7 α β γ δ ε ζ η
4 5 6 7 . . . 4 5 6 7 5 6 7 δ ε ζ η . . .
. . 4 5 6 7 . 4 5 4 5 6 7 5 . . δ ε ζ η .
. . 4 5 6 7 . 4 5 4 5 6 7 5 . . δ ε ζ η .
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::shift_right() algorithm

// (1)
constexpr ranges::subrange<I>
shift_right( I first, S last, std::iter_difference_t<I> n );

// (2)
constexpr ranges::borrowed_subrange_t<R>
shift_right( R&& r, ranges::range_difference_t<R> n );

The type of arguments are generic and have the following constraints:

  • I - std::permutable
  • S - std::sentinel_for<I>
  • R - std::ranges::forward_range

Additionally, each overload has the following constraints:

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

(The std:: namespace was ommitted here for readability)

Shifts the elements in the range [first; last) or r by n positions.

  • (1) Shifts the elements towards the end of the range:

    • If n == 0 || n >= last - first, there are no effects.
    • If n < 0, the behavior is undefined.
    • Otherwise, for every integer i in [0; last - first - n), moves the element originally at position first + i to position first + n + i.

    If I models bidirectional_iterator, then the moves are performed in decreasing order of i starting from last - first - n - 1.

  • ** (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.

Undefined Behaviour

The behavior is undefined

if [first; last) is not a valid range.

Parameters

first
last

The original range.

r

The range of elements to shift.

n

The number of positions to shift.

Return value

{
first,
/* NEW_LAST */
}

Where NEW_LAST is the end of the resulting range and equivalent to:

  • If n is less than last - first, first + n.
  • Otherwise, last.

Complexity

At most ranges::distance(first, last) - n assignments or swaps.

Exceptions

(none)

Notes

ranges::shift_right / ranges::shift_right has better efficiency on common implementations if I models bidirectional_iterator or random_access_iterator.

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 <string>
#include <type_traits>
#include <vector>

struct S
{
int value {0};
bool specified_state {true};

S(int v = 0) : value {v} {}
S(S const& rhs) = default;
S(S&& rhs) { *this = std::move(rhs); }
S& operator=(S const& rhs) = default;
S& operator=(S&& rhs)
{
if (this != &rhs)
{
value = rhs.value;
specified_state = rhs.specified_state;
rhs.specified_state = false;
}
return *this;
}
};

template<typename T>
std::ostream& operator<<(std::ostream& os, std::vector<T> const& v)
{
for (const auto& s : v)
{
if constexpr (std::is_same_v<T, S>)
s.specified_state ? os << s.value << ' ' : os << ". ";
else if constexpr (std::is_same_v<T, std::string>)
os << (s.empty() ? "." : s) << ' ';
else
os << s << ' ';
}
return os;
}

int main()
{
std::cout << std::left;

std::vector<S> a {1, 2, 3, 4, 5, 6, 7};
std::vector<int> b {1, 2, 3, 4, 5, 6, 7};
std::vector<std::string> c {"α", "β", "γ", "δ", "ε", "ζ", "η"};

std::cout << "vector<S> \tvector<int> \tvector<string>\n";
std::cout << a << " " << b << " " << c << '\n';

std::ranges::shift_left(a, 3);
std::ranges::shift_left(b, 3);
std::ranges::shift_left(c, 3);
std::cout << a << " " << b << " " << c << '\n';

std::ranges::shift_right(a, 2);
std::ranges::shift_right(b, 2);
std::ranges::shift_right(c, 2);
std::cout << a << " " << b << " " << c << '\n';

std::ranges::shift_left(a, 8); // has no effect: n >= last - first
std::ranges::shift_left(b, 8); // ditto
std::ranges::shift_left(c, 8); // ditto
std::cout << a << " " << b << " " << c << '\n';

// std::ranges::shift_left(a, -3); // UB
}
Output
vector<S>       vector<int>     vector<string>
1 2 3 4 5 6 7 1 2 3 4 5 6 7 α β γ δ ε ζ η
4 5 6 7 . . . 4 5 6 7 5 6 7 δ ε ζ η . . .
. . 4 5 6 7 . 4 5 4 5 6 7 5 . . δ ε ζ η .
. . 4 5 6 7 . 4 5 4 5 6 7 5 . . δ ε ζ η .
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.