Since the data structure are something like

struct morph
{
  size_t num;
  std::string name;
  //and so on
}

I have to find the different of the two sets with functor or some 3rd party
where could I find something like this?
Below is the implementation alter by me(refer to cplusplus.com)

template <class InputIterator1, class InputIterator2, class OutputIterator, typename binary_predicate>
OutputIterator set_difference_if (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, 
                                  InputIterator2 last2, OutputIterator result,  binary_predicate OP)
{
	while (first1 != last1 && first2 != last2)
	{
		if ( OP(*first1, *first2) )
		{
			*result = *first1;
			++result;
			++first1;
		}
		else if ( OP(*first2, *first1) )
		{
			++first2;
		}
		else { ++first1; ++first2; }
	}
	return std::copy(first1, last1, result);
}

struct morph
{
	size_t num;	
};

int main()
{							
        std::array<morph, 5> A;
	std::array<morph, 3> B;
	for(size_t i = 0; i != A.size(); ++i) A[i].num = i;
	B[0].num = 1; B[1].num = 3; B[2].num = 4;
	std::vector<morph> C;
	set_difference_if(A.begin(), A.end(), B.begin(), B.end(),       std::back_inserter(C), [](morph const A, morph const B){ return A.num < B.num; } );
	for(auto it = C.begin(); it != C.end(); ++it) std::cout<<it->num;
	std::cout<<std::endl;

Is this code safe or not?If it is safe, I may refine the code later

The other way is use std::find_if to iterate every element and save those different
elements into vector too

Recommended Answers

All 10 Replies

Um...set_difference() already has an overload that takes a predicate. Your call will work as-is:

std::set_difference(
    A.begin(), A.end(), B.begin(), B.end(), std::back_inserter(C),
    [](morph const A, morph const B) { return A.num < B.num; });

sorry, I haven't noticed, thanks

looks like I have to implement one for myself since the types
of the containers are different

template <class InputIterator1, class InputIterator2, class OutputIterator, typename binary_predicate>
OutputIterator set_difference_if (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2,
                                  InputIterator2 last2, OutputIterator result,  binary_predicate OP)
{
        while (first1 != last1 && first2 != last2)
        {
                if ( OP(*first1, *first2) )
                {
                        *result = *first1;
                        ++result;
                        ++first1;
                }
                else if ( OP(*first1, *first2) )
                {
                        ++first2;
                }
                else { ++first1; ++first2; }
        }
        return std::copy(first1, last1, result);
}

apparently, this kind of codes can't work
it would omit the state of "=="
The easiest way I could think of is pass in another functor

template <class InputIterator1, class InputIterator2, class OutputIterator,
          typename binary_predicate_1, typename binary_predicate_2>
OutputIterator set_difference_if (InputIterator1 first1, InputIterator1 last1, InputIterator2 first2,
                                  InputIterator2 last2, OutputIterator result,  binary_predicate_1 OP1,
                                  binary_predicate_2 OP2)
{
       while (first1 != last1 && first2 != last2)
        {
                if ( OP1(*first1, *first2) )
                {
                        *result = *first1;
                        ++result;
                        ++first1;
                }
                else if ( OP2(*first1, *first2) )
                {
                        ++first2;
                }
                else { ++first1; ++first2; }
        }
        return std::copy(first1, last1, result);
}

And design two functor for it like

struct difference_set_1 : public std::binary_function<morph, morph2, bool>
{
  bool operator()( morph const &Fir, morph2 const &Sec) const
  {
    return Fir.num < Sec.num;
  }
};

struct difference_set_2 : public std::binary_function<morph, morph2, bool>
{
  bool operator()( morph const &Fir, morph2 const &Sec) const
  {
    return Fir.num > Sec.num;
  }
};

Do you have any better ideas?
I just cover boost::range provided us a lot of algorithms
could it help me solve this kind of situation?Thanks

since the types of the containers are different

Can you clarify what you mean by this?

like

struct A
{
  size_t num;
};

struct B
{
  size_t num;
};

int main()
{
  std::vector<A>;
  std::vector<B>;
  //whatever, i have to find out the different "num" of A and B
}

I come up a way to generate the other functor for me

template<typename U, typename T, template<typename, typename> class binary_functor_1>
struct template_param_swap
{
  template<typename J, typename K>
  struct func2_wrap
  {
    binary_functor_1<K, J> func1;
    binary_functor_1<J, K> func2;
  };
  func2_wrap<T, U> func;
};

with this

template<typename T, typename U>
struct difference_set : public std::binary_function<T, U, bool>
{
  bool operator()( T const &Fir, U const &Sec) const
  {
    return Fir.num < Sec.num;
  }
};

code like this is possible

set_difference_if(A.begin(), A.end(), B.begin(), B.end(), std::back_inserter(C),
                          template_param_swap<morph, morph2, difference_set>() );

Why not use a functor with a template call-operator. That's the way I usually take care of this kind of problem. You can also use overloading rules (and even Sfinae) if you want different implementations for different pairs of types. Here is what I mean:

struct difference_set
{
  template <typename T, typename U>
  bool operator()( T const &Fir, U const &Sec) const
  {
    return Fir.num < Sec.num;
  }
};

Then you can just call set_difference_if (the original implementation) like this:

set_difference_if(A.begin(), A.end(), B.begin(), B.end(), std::back_inserter(C), difference_set() );

What's wrong with that? If you need two behaviours for different type pairs, then just make various overloads (or Sfinae-switched template overloads) of the operator() in your functor class. It's as easy as that.

mike_2000_17, thanks a lot
your solution is elegant and far more better than mine

Oops, I omitted one thing
the two data types are like these

struct A
{
  size_t num_one;
};

struct B
{
  size_t num_two;
};

looks like I have to choose the solution with two functors
or just copy the data into two different vectors

Just do like I said, overload the call operator in your functor:

struct difference_set
{
  bool operator()( A const &Fir, B const &Sec) const
  {
    return Fir.num_one < Sec.num_two;
  }

  bool operator()( B const &Fir, A const &Sec) const
  {
    return Fir.num_two < Sec.num_one;
  }
};
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.