Namespaces
Variants

std::set_difference

ja.cppreference.net から
 
 
アルゴリズムライブラリ
制約付きアルゴリズムとレンジのアルゴリズム (C++20)
制約付きアルゴリズム、例:ranges::copy、ranges::sort、...
ソートと関連操作
分割操作
(C++11)    

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


 
Defined in header <algorithm>
template< class InputIt1, class InputIt2, class OutputIt >
OutputIt set_difference( InputIt1 first1, InputIt1 last1,
                         InputIt2 first2, InputIt2 last2,
                         OutputIt d_first );
(1) (constexpr since C++20)
template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2, class ForwardIt3 >
ForwardIt3 set_difference( ExecutionPolicy&& policy,
                           ForwardIt1 first1, ForwardIt1 last1,
                           ForwardIt2 first2, ForwardIt2 last2,
                           ForwardIt3 d_first );
(2) (since C++17)
template< class InputIt1, class InputIt2,
          class OutputIt, class Compare >
OutputIt set_difference( InputIt1 first1, InputIt1 last1,
                         InputIt2 first2, InputIt2 last2,
                         OutputIt d_first, Compare comp );
(3) (constexpr since C++20)
template< class ExecutionPolicy,
          class ForwardIt1, class ForwardIt2,
          class ForwardIt3, class Compare >
ForwardIt3 set_difference( ExecutionPolicy&& policy,
                           ForwardIt1 first1, ForwardIt1 last1,
                           ForwardIt2 first2, ForwardIt2 last2,
                           ForwardIt3 d_first, Compare comp );
(4) (since C++17)

ソート済み範囲 [first1, last1) のうち、ソート済み範囲 [first2, last2) に含まれない要素を、d_first を先頭とする範囲にコピーします。出力範囲もソートされます。

[first1, last1) に互いに同等な要素が m 個含まれており、[first2, last2) にそれらと同等な要素が n 個含まれている場合、最終的に std::max(m - n, 0) 個の要素が [first1, last1) から出力範囲にコピーされ、順序は保持されます。

1) [first1, last1) または [first2, last2) が (C++20 まで)(C++20 から)operator< に関して std::less{}ソート されていない場合、動作は未定義です。
3) [first1, last1) または [first2, last2) が comp に関してソートされていない場合、動作は未定義です。
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 から)

出力範囲が [first1, last1) または [first2, last2) と重なる場合、動作は未定義です。

パラメータ

first1, last1 - 検査対象の最初の入力ソート済み 範囲 を定義するイテレータのペア
first2, last2 - 検索対象の2番目の入力ソート済み 範囲 を定義するイテレータのペア
d_first - 出力範囲の先頭
policy - 使用する 実行ポリシー
comp - 比較関数オブジェクト(つまり、 Compare の要件を満たすオブジェクト)。最初の引数が2番目の引数より 小さい (つまり、順序付けにおいて 前に来る )場合に​ true を返す。

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

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

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

型要件
-
InputIt1, InputIt2 は LegacyInputIterator の要件を満たさなければならない。
-
OutputIt は LegacyOutputIterator の要件を満たさなければならない。
-
ForwardIt1, ForwardIt2, ForwardIt3 は LegacyForwardIterator の要件を満たさなければならない。
-
Compare は Compare の要件を満たさなければならない。

戻り値

構築された範囲の終端を超えるイテレータ。

計算量

N 1 を std:: distance ( first1, last1 ) として、 N 2 を std:: distance ( first2, last2 ) として定義する:

1,2) 最大 2⋅(N 1 +N 2 )-1 回の比較を使用 operator < (C++20以前) std:: less { } (C++20以降) .
3,4) 最大 2⋅(N 1 +N 2 )-1 回の比較関数 comp の適用。

例外

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

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

実装例

set_difference (1)
template<class InputIt1, class InputIt2, class OutputIt>
OutputIt set_difference(InputIt1 first1, InputIt1 last1,
                        InputIt2 first2, InputIt2 last2, OutputIt d_first)
{
    while (first1 != last1)
    {
        if (first2 == last2)
            return std::copy(first1, last1, d_first);
        if (*first1 < *first2)
            *d_first++ = *first1++;
        else
        {
            if (! (*first2 < *first1))
                ++first1;
            ++first2;
        }
    }
    return d_first;
}
set_difference (3)
template<class InputIt1, class InputIt2, class OutputIt, class Compare>
OutputIt set_difference(InputIt1 first1, InputIt1 last1,
                        InputIt2 first2, InputIt2 last2, OutputIt d_first, Compare comp)
{
    while (first1 != last1)
    {
        if (first2 == last2)
            return std::copy(first1, last1, d_first);
        if (comp(*first1, *first2))
            *d_first++ = *first1++;
        else
        {
            if (!comp(*first2, *first1))
                ++first1;
            ++first2;
        }
    }
    return d_first;
}
HTMLタグ、属性、``、`
`、``タグ内のテキスト、およびC++固有の用語は翻訳せず、元のフォーマットを保持しました。

例

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
template<typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v)
{
    os << '{';
    for (auto n{v.size()}; const auto& e : v)
        os << e << (--n ? ", " : "");
    return os << '}';
}
struct Order // 非常に興味深いデータを持つ構造体
{
    int order_id{};
    friend std::ostream& operator<<(std::ostream& os, const Order& ord)
    {
        return os << ord.order_id;
    }
};
int main()
{
    const std::vector<int> v1{1, 2, 5, 5, 5, 9};
    const std::vector<int> v2{2, 5, 7};
    std::vector<int> diff;
    std::set_difference(v1.begin(), v1.end(), v2.begin(), v2.end(),
                        std::inserter(diff, diff.begin()));
    std::cout << v1 << " ∖ " << v2 << " == " << diff << "\n\n";
    // 古い状態と新しい状態の間でどの注文が「カット」されたかを知りたい:
    std::vector<Order> old_orders{{1}, {2}, {5}, {9}};
    std::vector<Order> new_orders{{2}, {5}, {7}};
    std::vector<Order> cut_orders;
    std::set_difference(old_orders.begin(), old_orders.end(),
                        new_orders.begin(), new_orders.end(),
                        std::back_inserter(cut_orders),
                        [](auto& a, auto& b) { return a.order_id < b.order_id; });
    std::cout << "old orders: " << old_orders << '\n'
              << "new orders: " << new_orders << '\n'
              << "cut orders: " << cut_orders << '\n';
}

出力:

{1, 2, 5, 5, 5, 9} ∖ {2, 5, 7} == {1, 5, 5, 9}
old orders: {1, 2, 5, 9}
new orders: {2, 5, 7}
cut orders: {1, 9}

不具合報告

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

DR 適用対象 公開時の動作 正しい動作
LWG 291 C++98 入力範囲における等価な要素の扱い方が規定されていなかった 規定された

関連項目

あるシーケンスが別のシーケンスの部分列であるかどうかを判定する
(関数テンプレート & アルゴリズム関数オブジェクト)
2つの集合の対称差を計算する
(関数テンプレート & アルゴリズム関数オブジェクト)
2つの集合の差を計算する
(アルゴリズム関数オブジェクト)