Anand
Anand

Reputation: 1122

set_difference for a custom structure

I am trying to find the difference between the following two sets:

A = {(0,0), (0,1), (1,0), (1,1), (2,2)}

B = {(0,0), (0,1), (1,0), (1,1)}

The answer I am expecting is

A - B = {(2,2)}

I tried the following code. But I am stuck unable to compile. Can anyone point out the mistake I am making?

#include <vector>
#include <algorithm>
#include <iostream>
#include <utility>

using namespace std;

class compare
{
  public:
    bool operator()(const pair <int, int> elem1, const pair <int, int> elem2)
    {
      return ((elem1.first == elem2.first) && 
          (elem1.second == elem2.second));
    }
};

int main()
{
  vector < pair<int, int> > v, va, vb;
  va.push_back(make_pair(0,0));
  va.push_back(make_pair(0,1));
  va.push_back(make_pair(1,0));
  va.push_back(make_pair(1,1));
  va.push_back(make_pair(2,2));

  vb.push_back(make_pair(0,0));
  vb.push_back(make_pair(0,1));
  vb.push_back(make_pair(1,0));
  vb.push_back(make_pair(1,1));


  vector < pair<int, int> >::iterator it, result;
  result = set_difference (va.begin(), va.end(),
      vb.begin(), vb.end(), 
      inserter(v, v.end()), 
      compare());

  // for (it = v.begin( ) ; it != result; it++)
  //   cout << "(" << it->first << it->second << ")" << ", ";
  // cout << endl;

  return 0;
}

EDIT: The compile error message is the following:

set_difference.cc: In function `int main()':
set_difference.cc:36: error: no match for 'operator=' in 'result = std::set_difference [with _InputIterator1 = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >, _InputIterator2 = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >, _OutputIterator = std::insert_iterator<std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >, _Compare = compare]((&va)->std::vector<_Tp, _Alloc>::begin [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), (&va)->std::vector<_Tp, _Alloc>::end [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), (&vb)->std::vector<_Tp, _Alloc>::begin [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), (&vb)->std::vector<_Tp, _Alloc>::end [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >](), std::inserter [with _Container = std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >, _Iterator = __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >](((std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > >&)(&v)), (&v)->std::vector<_Tp, _Alloc>::end [with _Tp = std::pair<int, int>, _Alloc = std::allocator<std::pair<int, int> >]()), (compare(), compare()))'
/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_iterator.h:587: note: candidates are: __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >& __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >::operator=(const __gnu_cxx::__normal_iterator<std::pair<int, int>*, std::vector<std::pair<int, int>, std::allocator<std::pair<int, int> > > >&)

Upvotes: 0

Views: 3539

Answers (3)

Kerrek SB
Kerrek SB

Reputation: 477408

(This is addressing the correctness of the algorithms, not the compilation problems.)

Read the documentation: The two input ranges already have to be sorted.

You also have to provide an output iterator for the result.

So do this:

std::sort(va.begin(), va.end(), compare());
std::sort(vb.begin(), vb.end(), compare());

set_difference(va.begin(), va.end(), vb.begin(), vb.end(),
               std::back_inserter(v), compare());

Your compare function should also define a strict, weak ordering, not an equality comparison.

By the way, std::pair<S, T> and std::tuple<T...> already come with built-in lexicographic comparison, so you shouldn't usually need to define your own comparison, unless you want something exotic: std::sort(va.begin(), va.end()); etc.

Upvotes: 3

celtschk
celtschk

Reputation: 19731

OK, now with the error message posted it's clear what is the problem: set_difference returns the output iterator, which in this case is an insert_iterator (constructed by your call to inserter). You try to assign it to result which is a vector iterator. This is a type mismatch.

The simplest solution would be to just omit that assignment and the iterator result because you don't need that iterator anyway; the results have been written to v.

Upvotes: 1

celtschk
celtschk

Reputation: 19731

Your expectation is wrong: A - B is the set of elements in A not also found in B, which in your case is the empty set because every element in A is also found in B. B - A would give the result you expect.

Upvotes: 1

Related Questions