# std::rotate

< cpp‎ | algorithm

定义于头文件 `<algorithm>` |  |
| (1) |
template< class ForwardIt > void rotate( ForwardIt first, ForwardIt n_first, ForwardIt last ); |  | (C++11 前)
template< class ForwardIt > ForwardIt rotate( ForwardIt first, ForwardIt n_first, ForwardIt last ); |  | (C++11 起) (C++20 前)
template< class ForwardIt > constexpr ForwardIt rotate( ForwardIt first, ForwardIt n_first, ForwardIt last ); |  | (C++20 起)
template< class ExecutionPolicy, class ForwardIt > ForwardIt rotate( ExecutionPolicy&& policy, ForwardIt first, ForwardIt n_first, ForwardIt last ); | (2) | (C++17 起)

1) 进行元素范围上的左旋转。
具体而言， `std::rotate` 交换范围 `[first, last)` 中的元素，方式满足元素 `n_first` 成为新范围的首个元素，而 `n_first - 1` 成为最后元素。
此函数的前提条件是 `[first, n_first)` 和 `[n_first, last)` 为合法范围。
2) 同 (1) ，但按照 `policy` 执行。此重载仅若 std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> (C++20 前)std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> (C++20 起) 为 true 才参与重载决议。

### 参数

first | - | 原范围的起始
n_first | - | 应出现在旋转后范围起始的元素
last | - | 原范围的结尾
policy | - | 所用的执行策略。细节见执行策略。
类型要求
- `ForwardIt` 必须满足值可交换 (ValueSwappable) 和 老式向前迭代器 (LegacyForwardIterator) 的要求。
- 解引用 `ForwardIt` 结果的类型必须满足可移动赋值 (MoveAssignable) 和可移动构造 (MoveConstructible) 的要求。

### 返回值

（无） | (C++11 前)
指向 `first` 指向的元素所在的新位置的迭代器。等于 `first + (last - n_first)` 。 | (C++11 起)

### 复杂度

与 `first` 和 `last` 间的距离成线性。

### 异常

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

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

### 注解

在常见实现上，若 `ForwardIt` 满足老式双向迭代器 (LegacyBidirectionalIterator) 或（更好的）老式随机访问迭代器 (LegacyRandomAccessIterator) 则 `ranges::rotate` 有更高的效率。

实现（例如 MSVC STL ）可能在迭代器类型满足老式连续迭代器 (LegacyContiguousIterator) ，并且交换其值类型不调用非平凡的特殊成员函数或 ADL 所找到的 `swap` 时启用向量化。

### 可能的实现

参阅 libstdc++、 libc++ 和 MSVC STL 中的实现。

    template<class ForwardIt>
    constexpr // C++20 起
    ForwardIt // C++11 前为 void
    rotate(ForwardIt first, ForwardIt n_first, ForwardIt last)
    {
       if(first == n_first) return last;
       if(n_first == last) return first;

       auto read      = n_first;
       auto write     = first;
       auto next_read = first; // "read" 撞击 "last" 时的读取位置

       while(read != last) {
          if(write == next_read) next_read = read; // 跟踪 "first" 所至
          std::iter_swap(write++, read++);
       }

       // 旋转剩余序列到位置中
       (rotate)(write, next_read, last);
       return write;
    }

### 示例

`std::rotate` 是许多算法中的公共构建块。此示例演示插入排序。

    #include <vector>
    #include <iostream>
    #include <algorithm>

    auto print = [](auto const& remark, auto const& v) {
        std::cout << remark;
        for (int n: v)
            std::cout << n << ' ';
        std::cout << '\n';
    };

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

        print("before sort:\t\t", v);

        // 插入排序
        for (auto i = v.begin(); i != v.end(); ++i) {
            std::rotate(std::upper_bound(v.begin(), i, *i), i, i+1);
        }

        print("after sort:\t\t", v);

        // 简单向左旋转
        std::rotate(v.begin(), v.begin() + 1, v.end());

        print("simple rotate left:\t", v);

        // 简单向右旋转
        std::rotate(v.rbegin(), v.rbegin() + 1, v.rend());

        print("simple rotate right:\t", v);
    }

输出：

    before sort:            2 4 2 0 5 10 7 3 7 1
    after sort:             0 1 2 2 3 4 5 7 7 10
    simple rotate left:     1 2 2 3 4 5 7 7 10 0
    simple rotate right:    0 1 2 2 3 4 5 7 7 10

### 参阅

rotate_copy | 复制并旋转元素范围 (函数模板)
ranges::rotate (C++20) | 旋转范围中的元素顺序 (niebloid)