Namespaces
Variants

std::rotate

ja.cppreference.net より
 
 
アルゴリズムライブラリ
制約付きアルゴリズムと範囲に対するアルゴリズム (C++20)
制約付きアルゴリズム (例: ranges::copy, ranges::sort, ...)
ソートおよび関連操作
分割操作
(C++11)    

ソート操作
二分探索操作
(分割された範囲に対する)
集合操作 (ソート済み範囲に対する)
マージ操作 (ソート済み範囲に対する)
ヒープ操作
最小/最大操作
(C++11)
(C++17)
辞書順比較操作
順列操作


 
ヘッダ <algorithm>
template< class ForwardIt >
ForwardIt rotate( ForwardIt first, ForwardIt middle, ForwardIt last );
で定義 (1) (C++20 以降 constexpr)
template< class ExecutionPolicy, class ForwardIt >
ForwardIt rotate( ExecutionPolicy&& policy,
                  ForwardIt first, ForwardIt middle, ForwardIt last );
(2) (C++17 以降)
1) 要素範囲の左ローテーションを実行します。
具体的には、std::rotate 範囲 [first, last) 内の要素を、[first, middle) 内の要素が [middle, last) 内の要素の後に配置されるように交換し、両方の範囲内の要素の順序は保持されます。
2) (1) と同じですが、 (1)、policy に従って実行されます。
このオーバーロードは、次の式の値が true である場合にのみオーバーロード解決に参加します:

std::is_execution_policy_v<std::decay_t<ExecutionPolicy>>

(C++20 まで)

std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>>

(C++20 以降)

次の条件のいずれかが満たされる場合、動作は未定義です:

  • [first, middle) または [middle, last) が 有効な範囲 ではありません。
  • *first の型が Swappable ではありません。
(C++11 まで)
(C++11 以降)

パラメータ

first, last - 回転させる要素の 範囲 を定義するイテレータのペア
middle - 回転後の範囲の先頭に現れるべき要素
policy - 使用する 実行ポリシー
型要件
-
ForwardIt は LegacyForwardIterator の要件を満たさなければならない。

戻り値

* first によって元々参照されていた要素へのイテレータ。すなわち、 std:: distance ( middle, last ) 番目の first の次のイテレータ。

計算量

最大で std:: distance ( first, last ) 回のスワップ。

例外

ExecutionPolicy という名前のテンプレートパラメータを持つオーバーロードは、 以下のようにエラーを報告します:

  • アルゴリズムの一部として呼び出された関数の実行が例外をスローした場合、 ExecutionPolicy が 標準ポリシー のいずれかであるとき、 std::terminate が呼び出される。それ以外の ExecutionPolicy については、動作は実装定義である。
  • アルゴリズムがメモリの確保に失敗した場合、 std::bad_alloc がスローされる。

実装例

実装例については libstdc++ 、 libc++ および MSVC STL も参照してください。

template<class ForwardIt>
constexpr // C++20以降
ForwardIt rotate(ForwardIt first, ForwardIt middle, ForwardIt last)
{
    if (first == middle)
        return last;
    if (middle == last)
        return first;
    ForwardIt write = first;
    ForwardIt next_read = first; // 「read」が「last」に達したときの読み取り位置
    for (ForwardIt read = middle; read != last; ++write, ++read)
    {
        if (write == next_read)
            next_read = read; // 「first」が移動した位置を追跡
        std::iter_swap(write, read);
    }
    // 残りのシーケンスを適切な位置に回転
    rotate(write, next_read, last);
    return write;
}

注記

std::rotate は、 ForwardIt が LegacyBidirectionalIterator または(さらに良い場合) LegacyRandomAccessIterator を満たす場合、一般的な実装ではより高い効率性を発揮します。

実装(例: MSVC STL )は、イテレータ型が LegacyContiguousIterator を満たし、その値型の交換が非自明な特殊メンバ関数も ADL で見つかった swap も呼び出さない場合、ベクトル化を有効化することがあります。

例

std::rotate は多くのアルゴリズムで共通して使用される構成要素です。この例では 挿入ソート を実演しています。

#include <algorithm>
#include <iostream>
#include <vector>
auto print = [](const auto remark, const auto& v)
{
    std::cout << remark;
    for (auto 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);
    // insertion sort
    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);
    // simple rotation to the left
    std::rotate(v.begin(), v.begin() + 1, v.end());
    print("simple rotate left:\t", v);
    // simple rotation to the right
    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

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
LWG 488 C++98 first が指す要素の新しい位置が返されなかった 返される

関連項目

要素の範囲をコピーして回転させる
(関数テンプレート & アルゴリズム関数オブジェクト)
要素の範囲の順序を回転させる
(アルゴリズム関数オブジェクト)