stl::list remove_if

Started by
7 comments, last by swiftcoder 16 years, 4 months ago
I did like to know how should i go about doing if i wish to set the predicate function as a member function of a class? e.g:

class CTest
{
private:
   std::list<int> IntList;

   bool IsPositive(int a)
   {
       return (a > 0) ? true : false;
   };

public:
   void RemovePositiveNumber()
   {
      IntList.remove_if(IsPositive);
   };
}

CTest MyTest;
MyTest.RemovePositiveNumber();
It seems that remove_if does not accept IsPositive as a predicate. Is it syntatically wrong to put IsPositive as the predicate?
Advertisement
The predicate should be callable on it's own, but a member function needs an instance to be called. Making IsPositive a static member function, or free standing which I would prefer in this case, should be enough.
Given that your predicate can be a free function or static member, it probably should be. But it is possible:

IntList.remove_if(std::bind1st(std::mem_fun(&CTest::IsPositive),this));
I don't really understand the method:
IntList.remove_if(std::bind1st(std::mem_fun(&CTest::IsPositive),this));


I understand what bind1st is use for. However why is it that I need to bind the (this) pointer to the 1st argument of the mem_fun returned value, which is mem_fun_t?


Edit: If the predicates require 2 arguments like sort? Will mem_fun still work?

[Edited by - littlekid on December 3, 2007 12:23:53 PM]
A class could also be used.

struct IsPositive
{
bool operator()(int a)
{
return a > 0;
};
};


...

void RemovePositiveNumber()
{
IntList.remove_if(IsPositive());
};
Quote:Original post by littlekid
I don't really understand the method:
*** Source Snippet Removed ***

I understand what bind1st is use for. However why is it that I need to bind the (this) pointer to the 1st argument of the mem_fun returned value, which is mem_fun_t?


Edit: If the predicates require 2 arguments like sort? Will mem_fun still work?


For some information about the funky pointer to member function syntax, see here. If you're not a fan of obscure C++ syntax, look away now [smile]. (I think this post is a little beyond 'For Beginners' anyway)

With the class in question, std::mem_fun returns a functor that looks something like this (this is simplified though, templates removed etc):
struct Functor{    bool (CTest::*function)( int );    bool operator()( CTest *instance, int argument )    {        return (instance->*function)(argument);    }};


This functor requires two arguments.

std::remove_if takes a functor that takes a single argument. Using std::bind1st, we 'bind' the first parameter, in this case the CTest pointer, to 'this'. The resulting functor looks something like this:
struct Functor{    bool (CTest::*function)( int );    CTest *instance;    bool operator()( int argument )    {        return (instance->*function)(argument);    }};


As for functors making use of member functions taking two (or more) arguments, boost::bind may be able to handle it (I've never had reason to use it).
Quote:Original post by rip-off
As for functors making use of member functions taking two (or more) arguments, boost::bind may be able to handle it (I've never had reason to use it).

Yes, boost::bind does this very nicely, something like this:
boost::bind(&Class::memberFunction, this, _1, _2);

adding additional _N as needed. You can also swizzle arguments by changine the order of _Ns, or by omitting or duplicating them.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Ok thanks alot, I now understand the how to use bind1st and mem_fun. Maybe if i need to use a predicate that needs 2 argument, i might make it static, and use bind1st /bind2nd when needed.

Or could I write my own template that is similar to mem_fun1_t? but in this case accepting 2 arg? e.g a self created mem_fun2_t
Quote:Original post by littlekid
Or could I write my own template that is similar to mem_fun1_t? but in this case accepting 2 arg? e.g a self created mem_fun2_t


These can be tricky beasties to get right, so i would suggest using boost::bind instead, or just sticking to static/free functions. As far as I recall, boost::bind is a header library, meaning that you only need the headers to use it, rather than having to use a lib or dll, making it much simpler to distribute.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement