# std::shift_left, std::shift_right

< cpp‎ | algorithm

定义于头文件 `<algorithm>` |  |
template< class ForwardIt > constexpr ForwardIt shift_left( ForwardIt first, ForwardIt last, typename std::iterator_traits<ForwardIt>::difference_type n ); | (1) | (C++20 起)
template< class ExecutionPolicy, class ForwardIt > ForwardIt shift_left( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, typename std::iterator_traits<ForwardIt>::difference_type n ); | (2) | (C++20 起)
template< class ForwardIt > constexpr ForwardIt shift_right( ForwardIt first, ForwardIt last, typename std::iterator_traits<ForwardIt>::difference_type n ); | (3) | (C++20 起)
template< class ExecutionPolicy, class ForwardIt > ForwardIt shift_right( ExecutionPolicy&& policy, ForwardIt first, ForwardIt last, typename std::iterator_traits<ForwardIt>::difference_type n ); | (4) | (C++20 起)

将范围 `[first, last)` 中的元素迁移 `n` 个位置。

1) 向范围开端迁移元素。若 n <= 0 || n >= last - first 则无效果。若 n < 0 则行为未定义。否则，对于每个 [0, last - first - n) 中的整数 `i` ，移动原于位置 first + n + i 的元素到位置 first + i 。以 `i` 从 ​0​ 开始递增的顺序进行移动。
3) 向范围结尾迁移元素。若 n <= 0 || n >= last - first 则无效果。若 n < 0 则行为未定义。否则对于每个 [0, last - first - n) 中的整数 `i` ，移动原于位置 first + i 的元素到位置 first + n + i 。若 `ForwardIt` 满足老式双向迭代器 (LegacyBidirectionalIterator) 的要求，则以 `i` 从 last - first - n - 1 开始递减的顺序进行移动。
2,4) 分别同 (1) 与 (3) ，但按照 `policy` 执行并可能以任何顺序进行移动。这些重载仅若 std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> 为 true 才参与重载决议。

在原范围但不在新范围中的元素被置于合法但未指定的状态。

### 参数

first | - | 原范围的开端
last | - | 原范围的结尾
n | - | 要迁移的位置数
policy | - | 所用的执行策略。细节见执行策略。
类型要求
- `ForwardIt` 必须满足老式向前迭代器 (LegacyForwardIterator) 的要求。
- 对于重载 (3-4) `ForwardIt` 必须满足老式双向迭代器 (LegacyBidirectionalIterator) 的要求或值可交换 (ValueSwappable) 的要求。
- 解引用 `ForwardIt` 结果的类型必须满足可移动赋值 (MoveAssignable) 的要求。

### 返回值

1-2) 结果范围的结尾。若 `n` 小于 `last - first` ，则返回 `first + (last - first - n)` 。否则返回 `first` 。
3-4) 结果范围的开始。若 `n` 小于 `last - first` ，则返回 `first + n` 。否则返回 `last` 。

### 复杂度

1-2) 至多 std::distance(first, last) - n 次赋值。
3-4) 至多 std::distance(first, last) - n 次赋值或交换。

### 异常

拥有名为 `ExecutionPolicy` 的模板形参的重载按下列方式报告错误：

- 若作为算法一部分调用的函数的执行抛出异常，且 `ExecutionPolicy` 为标准策略之一，则调用 std::terminate 。对于任何其他 `ExecutionPolicy` ，行为是实现定义的。
- 若算法无法分配内存，则抛出 std::bad_alloc 。

### 示例

    #include <iostream>
    #include <algorithm>
    #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;
        }
    };

    std::ostream& operator<< (std::ostream& os, std::vector<S> const& v) {
        for (const auto& s : v)
            s.specified_state ? os << s.value << ' ' : os << "? ";
        return os << '\n';
    }

    int main()
    {
        std::vector<S> v{1,2,3,4,5,6,7};

        std::shift_left(v.begin(), v.end(), 8);  // 无效果： n >= last - first
        std::cout << v;
    //  std::shift_left(v.begin(), v.end(), -3); // UB ：例如分段错误。
        std::shift_left(v.begin(), v.end(), +3); // OK
        std::cout << v;

        std::shift_right(v.begin(), v.end(), 2); // OK
        std::cout << v;
    }

输出：

    1 2 3 4 5 6 7
    4 5 6 7 ? ? ?
    ? ? 4 5 6 7 ?

### 参阅

move (C++11) | 将某一范围的元素移动到一个新的位置 (函数模板)
move_backward (C++11) | 按从后往前的顺序移动某一范围的元素到新的位置 (函数模板)
rotate | 旋转范围中的元素顺序 (函数模板)