std::unique
| ヘッダー <algorithm> で定義 |
||
template< class ForwardIt > ForwardIt unique( ForwardIt first, ForwardIt last ); |
(1) | (C++20 以降 constexpr) |
| template< class ExecutionPolicy, class ForwardIt > ForwardIt unique( ExecutionPolicy&& policy, |
(2) | (C++17以降) |
template< class ForwardIt, class BinaryPred > ForwardIt unique( ForwardIt first, ForwardIt last, BinaryPred p ); |
(3) | (C++20 以降 constexpr) |
| template< class ExecutionPolicy, class ForwardIt, class BinaryPred > |
(4) | (C++17以降) |
範囲[first, last) から、同値な要素の連続した各グループから最初の要素以外をすべて削除し、範囲の新しい終端を示すイテレータを返します。
|
std::is_execution_policy_v<std::decay_t<ExecutionPolicy>> が true である。 |
(C++20まで) |
|
std::is_execution_policy_v<std::remove_cvref_t<ExecutionPolicy>> は true です。 |
(C++20以降) |
目次 |
[edit] 解説
削除は、削除されない要素が範囲の先頭に現れるように、範囲内の要素をシフトすることによって行われます。
- シフトは、コピー代入(C++11まで)ムーブ代入(C++11以降) によって行われます。
- 削除操作は安定しています。削除されない要素の相対順序は変わりません。
- 削除操作によって、
[first,last)の基になるシーケンスは短縮されません。返されたイテレータを result とすると、
[result,last)のすべてのイテレータは、依然としてデリファレンス可能です。
|
(C++11以降) |
[edit] パラメータ
| first, last | - | 処理する要素の 範囲 を定義するイテレータのペア |
| policy | - | 使用する 実行ポリシー |
| p | - | 要素が等しいと見なされる場合に true を返す二項述語。 述語関数のシグネチャは、以下と同等である必要がある。 bool pred(const Type1 &a, const Type2 &b); シグネチャは const & を持つ必要はないが、関数は渡されたオブジェクトを変更してはならず、値カテゴリに関わらず、(おそらく const の) |
| 型要件 | ||
-ForwardIt は LegacyForwardIterator の要件を満たさなければなりません。 | ||
-デリファレンスされた ForwardIt の型は、MoveAssignable の要件を満たす必要があります。 | ||
[edit] 戻り値
範囲の新しい終端を示す ForwardIt。
[edit] 計算量
std::distance(first, last) を N とする
[edit] 例外
ExecutionPolicy というテンプレートパラメータを持つオーバーロードは、次のようにエラーを報告します。
- アルゴリズムの一部として呼び出された関数の実行が例外をスローし、
ExecutionPolicyが 標準ポリシー のいずれかである場合、std::terminate が呼び出されます。その他のExecutionPolicyの場合、動作は実装定義です。 - アルゴリズムがメモリの割り当てに失敗した場合、std::bad_alloc がスローされます。
[edit] 実装例
libstdc++、libc++、および MSVC STL の実装を参照してください。
| unique (1) |
|---|
template<class ForwardIt> ForwardIt unique(ForwardIt first, ForwardIt last) { if (first == last) return last; ForwardIt result = first; while (++first != last) if (!(*result == *first) && ++result != first) *result = std::move(*first); return ++result; } |
| unique (3) |
template<class ForwardIt, class BinaryPredicate> ForwardIt unique(ForwardIt first, ForwardIt last, BinaryPredicate p) { if (first == last) return last; ForwardIt result = first; while (++first != last) if (!p(*result, *first) && ++result != first) *result = std::move(*first); return ++result; } |
[edit] 注記
unique の呼び出しの後には、通常、コンテナから要素を実際に削除するために、コンテナの erase メンバ関数が呼び出されます。
[edit] 例
#include <algorithm> #include <iostream> #include <vector> int main() { // a vector containing several duplicate elements std::vector<int> v{1, 2, 1, 1, 3, 3, 3, 4, 5, 4}; auto print = [&](int id) { std::cout << "@" << id << ": "; for (int i : v) std::cout << i << ' '; std::cout << '\n'; }; print(1); // remove consecutive (adjacent) duplicates auto last = std::unique(v.begin(), v.end()); // v now holds {1 2 1 3 4 5 4 x x x}, where 'x' is indeterminate v.erase(last, v.end()); print(2); // sort followed by unique, to remove all duplicates std::sort(v.begin(), v.end()); // {1 1 2 3 4 4 5} print(3); last = std::unique(v.begin(), v.end()); // v now holds {1 2 3 4 5 x x}, where 'x' is indeterminate v.erase(last, v.end()); print(4); }
出力
@1: 1 2 1 1 3 3 3 4 5 4 @2: 1 2 1 3 4 5 4 @3: 1 1 2 3 4 4 5 @4: 1 2 3 4 5
[edit] 不具合報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| LWG 202 | C++98 | 要素が 非同値関係で比較される場合、動作は不明瞭でした。 |
この場合の動作は 未定義となる |
[edit] 関連項目
| 等しい(または指定された述語を満たす)最初の2つの隣接する項目を見つける (関数テンプレート) | |
| 連続する重複を含まない要素の範囲のコピーを作成する (関数テンプレート) | |
| 特定の基準を満たす要素を削除する (関数テンプレート) | |
| 連続する重複した要素を削除する ( std::list<T,Allocator> のパブリックメンバ関数) | |
| 連続する重複した要素を削除する ( std::forward_list<T,Allocator> のパブリックメンバ関数) | |
| (C++20) |
範囲内の連続する重複要素を削除する (アルゴリズム関数オブジェクト) |