Namespaces
Variants

std::unique

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

ソート操作
二分探索操作
(分割された範囲に対して)
集合操作 (ソート済み範囲に対して)
マージ操作 (ソート済み範囲に対して)
ヒープ操作
最小値/最大値操作
(C++11)
(C++17)
辞書式比較操作
置換操作


 
ヘッダ <algorithm>
template< class ForwardIt >
ForwardIt unique( ForwardIt first, ForwardIt last );
で定義 (1) (C++20からconstexpr)
template< class ExecutionPolicy, class ForwardIt >
ForwardIt unique( ExecutionPolicy&& policy,
                  ForwardIt first, ForwardIt last );
(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 >
ForwardIt unique( ExecutionPolicy&& policy,
                  ForwardIt first, ForwardIt last, BinaryPred p );
(4) (C++17から)

範囲 [first, last) 内の連続する等価な要素の各グループから最初の要素を除くすべてを削除し、範囲の新しい終端を指す過去終端イテレータを返します。

1) 要素の比較は operator== を使用して行われます。
operator== が同値関係を確立しない場合、動作は未定義です。
3) 要素の比較は、指定された二項述語 p を使用して行われます。
p が同値関係を確立しない場合、動作は未定義です。
2,4) (1,3) と同じですが、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から)

説明

削除は、範囲内の要素をシフトすることで行われ、削除されない要素が範囲の先頭に現れるようにします。

  • シフト操作は copy assignment (until C++11) move assignment (since C++11) によって行われます。
  • 削除操作は安定しています:削除されない要素の相対的な順序は維持されます。
  • [ first , last ) の基となるシーケンスは削除操作によって短縮されません。返されるイテレータを result として指定します:
  • [ result , last ) の各要素は有効だが未規定の状態となる。なぜならムーブ代入によって、元々その範囲にあった要素からムーブすることで要素を除去する可能性があるため。
(C++11以降)

パラメータ

first, last - 処理する要素の範囲を定義するイテレータのペア
policy - 使用する実行ポリシー
p - 要素が等しいと見なされるべき場合に​ true を返す二項述語

述語関数のシグネチャは以下と同等であるべき:

bool pred ( const Type1 & a, const Type2 & b ) ;

シグネチャが const & を持つ必要はないが、関数は渡されたオブジェクトを変更してはならず、 値カテゴリ に関係なく型 (おそらくconstの) Type1 と Type2 のすべての値を受け入れられなければならない (したがって、 Type1 & は許可されない 、また Type1 も、 Type1 に対してムーブがコピーと等価でない限り許可されない (C++11以降) )。
型 Type1 と Type2 は、 ForwardIt 型のオブジェクトが間接参照され、それら両方に暗黙的に変換可能でなければならない。 ​

型要件
-
ForwardIt は LegacyForwardIterator の要件を満たさなければならない。
-
ForwardIt の間接参照された型は MoveAssignable の要件を満たさなければならない。

戻り値

範囲の新しい終端を指す ForwardIt 。

計算量

与えられた N を std:: distance ( first, last ) として:

1,2) 厳密に max(0,N-1) 回の比較を operator == を使用して行う。
3,4) 厳密に max(0,N-1) 回の述語 p の適用。

例外

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

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

実装例

実装例については 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;
}
**注記:** - HTMLタグ、属性、および``、`
`タグ内のC++コードは翻訳対象外として保持されています
- C++固有の用語(`template`、`class`、`ForwardIt`、`unique`、`std::move`など)は翻訳していません
- テーブルの構造と書式は完全に保持されています

注記

uniqueへの呼び出しは通常、コンテナのeraseメンバー関数への呼び出しが続き、実際にコンテナから要素を削除します。

例

#include <algorithm>
#include <iostream>
#include <vector>
int main()
{
    // 重複要素を含むベクター
    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);
    // 連続する重複要素を削除
    auto last = std::unique(v.begin(), v.end());
    // vは現在 {1 2 1 3 4 5 4 x x x} を保持('x'は不定値)
    v.erase(last, v.end());
    print(2);
    // ソート後にuniqueを適用して全ての重複を削除
    std::sort(v.begin(), v.end()); // {1 1 2 3 4 4 5}
    print(3);
    last = std::unique(v.begin(), v.end());
    // vは現在 {1 2 3 4 5 x x} を保持('x'は不定値)
    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

欠陥報告

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

DR 適用対象 公開時の動作 正しい動作
LWG 202 C++98 要素が同値関係ではない比較を使用する場合の
動作が不明確であった
この場合の動作は
未定義となる

関連項目

隣接する最初の2つの等しい要素(または指定された述語を満たすもの)を検索する
(関数テンプレート & アルゴリズム関数オブジェクト)
連続した重複を含まない範囲のコピーを作成する
(関数テンプレート & アルゴリズム関数オブジェクト)
特定の条件を満たす要素を削除する
(関数テンプレート & アルゴリズム関数オブジェクト)
連続した重複要素を削除する
(のパブリックメンバ関数 std::list<T,Allocator>)
連続した重複要素を削除する
(のパブリックメンバ関数 std::forward_list<T,Allocator>)
範囲内の連続した重複要素を削除する
(アルゴリズム関数オブジェクト)