set_intersection 用于两种不同类型的集合

发布于 2024-12-01 06:33:36 字数 963 浏览 2 评论 0原文

有没有办法对两种不同类型的集合执行 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 I 的 描述 来看知道我可以使用两个不同的迭代器。

我尝试搜索一些可以实现我想要的功能的代码示例,但没有找到任何代码示例?有人可以为我提供一个针对我的问题的工作代码示例吗?

更新: 错误是:

错误:stl_function.h:227:与“operator<”不匹配在 '__x <; __y'

提前致谢!

Is there any way to do std::set_intersection on two different types of sets?

I have two sets:

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

I'm able to define some comparator for them that checks if X1 and X2 are equal.

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

Now, I try to do a set intersection on those two sets:

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());

Unfortunately, I can't force this code to work. I'm not even sure if this is possible, but from the description of set_intersection I know that I can use two different iterators.

I tried to search for some code samples that do what I want, but didn't found any? Could someone present me a working code sample for my problem?

Update:
the error is:

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

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

空城仅有旧梦在 2024-12-08 06:33:36

PlasmaHH 的评论可能就是问题所在。

像 set_intersection 这样的函数的工作方式是首先执行: 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 ());
}

The comment by PlasmaHH is likely the problem.

The way functions like set_intersection work is they first do: a < b and then b < a

As a result ample_comparer needs to be able to compare both ways:

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;
    }
};

The following doesn't actually do anything sensible - but it does compile cleanly:

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 ());
}
り繁华旳梦境 2024-12-08 06:33:36

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

It won't work as both inputs must be assignable to the output iterator type. You might add some implicit conversion operators to X1, X2 which converts between them to get that working.

爱*していゐ 2024-12-08 06:33:36

我认为这是不可能的(至少没有用户定义的转换)。
来自文档中的“类型要求”部分:InputIterator1 和 InputIterator2具有相同的值类型。

I don't think it is possible as it is, (at least without user-defined conversion).
From the section "Requirements on types" in documentation: InputIterator1 and InputIterator2 have the same value type.

以歌曲疗慰 2024-12-08 06:33:36

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

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

First of all according to the docs set_intersection is using a operator<.
And second you can make a third struct that will extract from the type the fields you will use to do compare

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){ 
... }  )

You can go down this path and create a custom wrapper that can do anything unless your two types can compare

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;
     }
}

Something like that. I didn't test it and it won't compile but you get the point. Maybe something similiar is hidden something similiar somewhere in the STL libraries

Edit: Btw i think you can use some kind of variant type (boost::variant or std::variant) I think it does this already...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文