Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

set_intersection for two different types of sets

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!

like image 916
matekm Avatar asked Aug 24 '11 07:08

matekm


3 Answers

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 ());
}
like image 62
Richard Corden Avatar answered Sep 22 '22 11:09

Richard Corden


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.

like image 21
Anteru Avatar answered Sep 18 '22 11:09

Anteru


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.

like image 35
vine'th Avatar answered Sep 22 '22 11:09

vine'th