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.

Daily bit(e) C++

Алгоритмы 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 не был перемещен

Пример на Compiler Explorer

Теги

C++ / CppSTL / Standard Template Library / Стандартная библиотека шаблоновПрограммирование