Daily bit(e) C++. std::shift_left, std::shift_right
Добавлено 10 апреля 2026 в 06:25
Daily bit(e) C++ 22. Два алгоритма, которые сдвигают все элементы в диапазоне влево или вправо на заданное смещение: std::shift_left, std::shift_right.

Алгоритмы C++20 std::shift_left и std::shift_right перемещают элементы в заданном диапазоне на указанное смещение.
Оба алгоритма выполняют внутреннее перемещение, то есть мы можем имитировать эти алгоритмы вручную, вызвав алгоритм std::move с соответствующим источником и местом назначения смещения. Однако std::shift_left и std::shift_right значительно снижают вероятность ошибок в этом процессе.
Оба алгоритма имеют параллельную версию (C++20) и версию для диапазонов (C++23).
#include <vector>
#include <algorithm>
#include <utility>
struct EmptyOnMove
{
char value;
EmptyOnMove(char value) : value(value) {}
EmptyOnMove(EmptyOnMove&& src)
: value(std::exchange(src.value,'-')) {}
EmptyOnMove& operator=(EmptyOnMove&& src)
{
value = std::exchange(src.value, '-');
return *this;
}
EmptyOnMove(const EmptyOnMove&) = default;
EmptyOnMove& operator=(const EmptyOnMove&) = default;
};
// Для примитивных типов перемещение ведет себя, как копирование
std::vector<int> data{1,2,3,4,5,6,7,8,9};
std::shift_left(data.begin(), data.end(), 3);
// data == {4, 5, 6, 7, 8, 9, 7, 8, 9}
// Аналогично следующему:
data = {1,2,3,4,5,6,7,8,9};
std::move(data.begin()+3, data.end(), data.begin());
// data == {4, 5, 6, 7, 8, 9, 7, 8, 9}
data = {1,2,3,4,5,6,7,8,9};
std::shift_right(data.begin(), data.end(), 3);
// data == {1, 2, 3, 1, 2, 3, 4, 5, 6}
// Аналогично следующему:
data = {1,2,3,4,5,6,7,8,9};
std::move_backward(data.begin(), data.end()-3, data.end());
// data == {1, 2, 3, 1, 2, 3, 4, 5, 6}
// Демонстрация перемещения с типом, который устанавливает
// свое значение в '-', когда выполняется перемещение из него.
std::vector<EmptyOnMove> nontrivial{{'a'},{'b'},{'c'},{'d'},
{'e'},{'f'},{'g'}};
std::shift_right(nontrivial.begin(), nontrivial.end(), 4);
// nontrivial == {---dabc}
// abc были перемещены, следовательно исходные элементы имеют значение '-'
// d не был перемещен
