Przejdź do głównej zawartości

std::shift_left() algorithm

// (1)
template< class ForwardIt >
constexpr ForwardIt
shift_left( ForwardIt first, ForwardIt last,
typename std::iterator_traits<ForwardIt>::difference_type n );

// (2)
template< class ExecutionPolicy, class ForwardIt >
ForwardIt
shift_left( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
typename std::iterator_traits<ForwardIt>::difference_type n );
  • (1) Shifts the elements towards the beginning 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 + n + i to position first + i. The moves are performed in increasing order of i starting from 0.

  • (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::remove_cvref_t<ExecutionPolicy>> is true.

Parameters

first
last

The original range.

n

The number of positions to shift.

policy

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

Type requirements

ForwardItLegacyForwardIterator

The type of dereferenced ForwardIt must meet the requirements of MoveAssignable.

Return value

The end of the resulting range:

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

Complexity

At most std::distance(first, last) - n assignments.

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 none other ExecutionPolicy, the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

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::shift_left(begin(a), end(a), 3);
std::shift_left(begin(b), end(b), 3);
std::shift_left(begin(c), end(c), 3);
std::cout << a << " " << b << " " << c << '\n';

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

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

// std::shift_left(begin(a), end(a), -3); // UB, e.g. segfault.)
}
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::shift_left() algorithm

// (1)
template< class ForwardIt >
constexpr ForwardIt
shift_left( ForwardIt first, ForwardIt last,
typename std::iterator_traits<ForwardIt>::difference_type n );

// (2)
template< class ExecutionPolicy, class ForwardIt >
ForwardIt
shift_left( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last,
typename std::iterator_traits<ForwardIt>::difference_type n );
  • (1) Shifts the elements towards the beginning 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 + n + i to position first + i. The moves are performed in increasing order of i starting from 0.

  • (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::remove_cvref_t<ExecutionPolicy>> is true.

Parameters

first
last

The original range.

n

The number of positions to shift.

policy

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

Type requirements

ForwardItLegacyForwardIterator

The type of dereferenced ForwardIt must meet the requirements of MoveAssignable.

Return value

The end of the resulting range:

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

Complexity

At most std::distance(first, last) - n assignments.

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 none other ExecutionPolicy, the behavior is implementation-defined.
  • If the algorithm fails to allocate memory, std::bad_alloc is thrown.

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::shift_left(begin(a), end(a), 3);
std::shift_left(begin(b), end(b), 3);
std::shift_left(begin(c), end(c), 3);
std::cout << a << " " << b << " " << c << '\n';

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

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

// std::shift_left(begin(a), end(a), -3); // UB, e.g. segfault.)
}
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.