Making the right predicates

I have recently been learning to use <functional>, and I am trying to build a predicate for the following problem:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct AA{
   int getValue(){return 8;}
   AA(int tmp){value=tmp;}
  private:
   int value;
};

main(){
AA a1(1);
AA a2(2);
AA a3(3);
AA a4(4);

std::list<AA> aList;
aList.push_back(a1);
aList.push_back(a2);
aList.push_back(a3);
aList.push_back(a4);
remove_if(aList.begin(),aList.end(), /*Predicate*/);

The predicate in the remove_if() should remove the element if the object's getValue() function returns a specified value. So, for each element, its member function getValue() will be called and the return value will be compared with a constant.

It looks like bind1st(or maybe bind2nd) with equal_to<int>, and also mem_fun_ref(&AA::getValue) will be useful, but I am not sure how to use them together.

If I used a for loop(I'm trying to avoid this), it would look like this:
1
2
3
4
5
6
7
ii=aList.begin();
while(ii != aList.end())
{if(77 == ii->getValue())
aList.remove(ii++);
else
++ii;
}

Also, if I were to overload the == operator (The class AA is from a library so I can't actually do this to solve), I could do it like this:
 
remove_if(aList.begin(),aList.end(), 77);
You could do it with the bind1st etc. but I don't think it improves readability.

I would prefer using a functor like this:
1
2
3
4
5
6
7
8
class Comparer
{
  int reference_;
public:
  Comparer(int reference) : reference_(reference) {};
  bool operator()(const AA& v) {return v.getValue() == reference_;}; // or v.getValue() < reference ...
};


So line 19 turns into:
 
remove_if(aList.begin(),aList.end(), Comparer(77));


The basic idea is: Put the variables that need to be flexible in the constructor. Adjust bool operator()(const AA&) to be the predicate you want.

If you don't make getValue a const function, change the signature to bool operator()(const AA&)

Btw. do you know that remove_if doesn't actually remove any elements from the list?
If not, take a look here: http://en.wikipedia.org/wiki/Erase-remove_idiom
Onur, thanks for the reply and your solution. Is there any reason not to use a binary function? It is probably just personal preference, but is there any other reason?
1
2
3
4
bool Comparer2(AA anA, int anInt)
{
return anA.getValue()==anInt;
}

1
2
pointer_to_binary_function <AA,int,bool> myComOb(Comparer2)
remove_if( aList.begin(),aList.end(), bind2nd(myComOb,3) );


Is there a way to do this without creating a new function or a new class?, also without modifying AA. What I'm actually doing is processing a list of ip addresses that are contained in Qt4's QHostAddress. The member function QHostAddress::protocol() returns QAbstractSocket::IPv6Protocol if it is an IPv6. So I am trying to delete all elements that are IPv6. And I am trying to minimize the amount of code (so I'm trying to avoid implementing an extra function or class). Also I'm just curious if it is possible.

Also, I did not know remove and remove_if actually just move the values to the end, and don't actually delete them. That would have caused me a huge headache later, thanks.
You can also use a function or combination of function and bind and achieve the same result.
I think I read somewhere that using a function object is more efficient since it can be better inlined. But that's not the main reason I prefer function objects. The main reason is that you maybe have a higher initial complexity (extra class) but the solution scales well with more demanding requirements (take for example the case when you want to reduce identical subsequent entries to only one occurence or other cases where you need to store some information from call to call).

And if you look at the next standard of C++, there will be lambda expressions which will probably supercede both functions and function objects in this case.

If you want to reduce the need to write too many classes, use functor templates that you can reuse more easily!
1
2
3
4
5
6
7
template<typename T>
class ComparesEqualTo
{
  T _ref;
  ComparesEqualTo(const T& ref) : _ref(ref) {};
  bool operator()(const T& val){return val == _ref;};
}


But it your case (with the IP addresses) I would stick with a functor specially designed for this purpose and the remove/erase idiom.

If you're interested you can take a look at boost lambda (http://www.boost.org/doc/libs/1_45_0/doc/html/lambda.html) which a adds limited support for lambda functions or if you are using Visual Studio 2010 you can use "native" lambda functions (http://msdn.microsoft.com/en-us/library/dd293608.aspx).

With the VS2010 lambda function it is possible to do it without an extra function or function object.
Topic archived. No new replies allowed.