2011-08-24 9 views
6

2種類のセットでstd :: set_intersectionを実行する方法はありますか?2種類のセットのset_intersection

私は2つのセットがあります:私はX1とX2が等しいかどうかをチェックする彼らのためにいくつかのコンパレータを定義することができるよ

std::set<X1> l_set1; 
std::set<X2> l_set2; 

を。

struct sample_comparer 
{ 
    bool operator()(const &X1 p_left, const &X2 p_right) 
    { 
     return p_left == p_right; 
    } 
}; 

は今、私はそれらの二組の上に積集合を実行しよう:

std::set<X1> l_intersect; 
std::set_intersection(l_set1.begin(), l_set1.end(), l_set2.begin(), l_set2.end(), 
         std::inserter(l_intersect, l_intersect.begin()), sample_comparer()); 

残念ながら、私はこのコードが動作するように強制することはできません。私はこれが可能かどうかも分かりませんが、set_intersectionのdescriptionから、私は2つの異なるイテレータを使用できることを知っています。

私が欲しいものを行うコードサンプルを検索しようとしましたが、何も見つかりませんでしたか?誰かが私の問題のための実用的なコードサンプルを私に提示できますか?

更新: エラーは、次のとおりです。事前に

error: stl_function.h:227: no match for 'operator<' in '__x < __y'

ありがとう!

+0

"残念ながら、私はこのコードを動作させることはできません。"どのようなコンパイルエラーがありますか? –

+1

あなたのサンプル比較者は正しいことをしません。それは、比較された要素に厳密な弱い順序を課すことよりも小さくする必要があります。 – tokage

+0

オーバーロードされた<演算子 'bool演算子<(X1、X2)' –

答えて

3

PlasmaHHによるコメントはおそらく問題です。

set_intersectionの作品のような機能は、彼らが最初に行うのある方法:a < b、その後b < a

結果ample_comparerは、両方の方法を比較できるようにする必要がありとおり:

struct sample_comparer 
{ 
    bool operator()(const &X1 p_left, const &X2 p_right) 
    { 
     return p_left == p_right; 
    } 
    bool operator()(const &X2 p_left, const &X1 p_right) 
    { 
     return p_left == p_right; 
    } 
}; 

次は実際には行いません。賢明なもの - しかし、それはきれいにコンパイルされます:

struct A 
{ 
    struct Compare { bool operator() (A const &, A const &) { return false;} }; 
}; 

struct B 
{ 
    struct Compare { bool operator() (B const &, B const &) { return false; } }; 
}; 

typedef std::set<A, A::Compare> S1; 
typedef std::set<B, B::Compare> S2; 

class IntersectionCompare 
{ 
public: 
    bool operator()(S1::value_type, S2::value_type) { return false; } 
    bool operator()(S2::value_type, S1::value_type) { return false; } 
}; 

void bar (S1 & s1, S2 & s2) 
{ 
    S1 result; 
    std::set_intersection (s1.begin() 
     , s1.end() 
     , s2.begin() 
     , s2.end() 
     , std :: insert_iterator<S1> (result, result.end()) 
     , IntersectionCompare()); 
} 
4

どちらの入力も出力イテレータタイプに割り当てる必要があるため、動作しません。暗黙的な変換演算子をX1、X2に追加して、それらの変換演算子を変換して動作させることもできます。

+0

set_intersectionの場合、出力範囲は1からの変換(どちらが指定されていなくても)。 set_unionやset_differenceのようなものは両方の型からの変換が必要です。 –

2

私はそれが可能であるとは思わない、少なくともユーザー定義の変換はありません。 documentationのセクションのタイプ:InputIterator1 and InputIterator2 have the same value type.

+0

答えを教えていただきありがとうございます。 – matekm

+0

値が同じである必要がある場合、関数は2つの異なる入力イテレータタイプを許可しますか? –

0

まず第一にすべてのドキュメントset_intersectオペレーター<を使用しています。 そして第二に、あなたが行うために使用するフィールドは、比較タイプから抽出されます第三の構造体を作ることができます

std::set<X1> l_set1; 
std::set<X2> l_set2; 
struct XCompare 
{   
    int value; 
    XCompare(const X1& x) 
    { 
     value = x.value; 
    } 

    XCompare(const X2& x) 
    { 
     value = x.value; 
    } 
} 

std::set_intersection(...,...,[](const XCompare& c1, const XCompare& c2){ 
... } ) 

あなたはこの道を行くと何かを行うことができますカスタムラッパーを作成することができない限り、あなたの二つのタイプすることができますそのような

template<typename T1, typename T2> 
struct ValueWrapper 
{ 
    T1 const* v1 = nullptr; 
    T2 const* v2 = nullptr; 

    ValueWrapper(const T1& value) 
    { 
     v1 = &value; 
    } 

    ValueWrapper(const T2& value) 
    { 
     v2 = &value; 
    } 

    bool operator<(const ValueWrapper& other) 
    { 
     if (v1 != nullptr) 
     { 
      if (other.v1 != nullptr) 
      { 
       return *v1 < *(other.v2) 
      } 

... }}

template<typename T1, typename T2> 
struct ValueWrapperComparator 
{ 
    bool operator()(ValueWrapper<T1,T2> v1, ValueWrapper<T1,T2> v2) 
    { 
     return v1 < v2; 
    } 
} 

何かを比較します。私はそれをテストしなかったし、コンパイルされませんが、あなたはポイントを得る。おそらく類似した何かがSTLライブラリのどこかに類似したものに隠されています

編集:Btw私はあなたが何らかのバリアント型(boost :: variantまたはstd :: variant)を使うことができると思います...