2011-08-24 119 views
6

有什麼辦法可以在兩種不同類型的集合上執行std :: set_intersection?set_intersection兩種不同類型的集合

我有兩套:

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

我能夠爲它們定義一些比較來檢查,如果X1和X2是相等的。

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我知道我可以使用兩個不同的迭代器。

我試圖搜索一些代碼示例,做我想要的,但沒有發現任何?有人能爲我的問題介紹一個有效的代碼示例嗎?

更新: 錯誤是:提前

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

謝謝!

+0

」不幸的是,我無法強制此代碼正常工作。「你得到什麼編譯器錯誤? –

+1

您的示例比較器沒有做正確的事情。它需要小於,對比較的元素施加嚴格的弱排序。 – tokage

+0

您是否嘗試提供一個超載的<運算符'布爾運算符<(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,輸出範圍只需要允許從一個的輸入(雖然沒有指定哪一個)。像set_union或set_difference之類的東西需要兩種類型的轉換。 –

2

我不認爲它是可能的,因爲它(至少沒有用戶定義的轉換)。 從documentationInputIterator1 and InputIterator2 have the same value type.

+0

感謝您的回答,並感謝您將解決方案指向文檔 – matekm

+0

爲什麼該函數允許兩種不同的輸入迭代器類型(如果值需要相同)? –

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庫中的某處

編輯:順便說一句我想你可以使用某種變體類型(boost :: variant或std :: variant)我認爲它已經這樣做了......