7

有什么方法可以对两种不同类型的集合执行 std::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 的描述中我知道我可以使用两个不同的迭代器。

我试图搜索一些我想要的代码示例,但没有找到?有人可以为我的问题提供一个工作代码示例吗?

更新:错误是:

错误:stl_function.h:227: '__x < __y' 中的 'operator<' 不匹配

提前致谢!

4

4 回答 4

5

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 ());
}
于 2011-08-24T12:05:42.520 回答
4

它不起作用,因为两个输入都必须可分配给输出迭代器类型。您可能会向 X1、X2 添加一些隐式转换运算符,它们在它们之间进行转换以使其正常工作。

于 2011-08-24T07:56:34.760 回答
2

我不认为它是可能的,(至少没有用户定义的转换)。从文档中的“类型要求”部分:InputIterator1 and InputIterator2 have the same value type.

于 2011-08-24T09:08:07.290 回答
0

首先根据文档 set_intersection 使用 operator<。其次,您可以创建第三个结构,该结构将从类型中提取用于比较的字段

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

于 2018-01-23T08:54:13.880 回答