2011-08-24 113 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)我认为它已经这样做了......

相关问题