2

I want to use std::remove_if with a predicate that is a member function of a differenct calss.

That is

class B;

class A {
    bool invalidB( const B& b ) const; // use members of class A to verify that B is invalid
    void someMethod() ;
};

Now, implementing A::someMethod, I have

void A::someMethod() {
    std::vector< B > vectorB; 
    // filling it with elements

    // I want to remove_if from vectorB based on predicate A::invalidB
    std::remove_if( vectorB.begin(), vectorB.end(), invalidB )
}

Is there a way to do this?

I have already looked into the solution of Idiomatic C++ for remove_if, but it deals with a slightly different case where the unary predicate of remove_if is a member of Band not A.

Moreover,
I do not have access to BOOST or c++11

Thanks!

Community
  • 1
  • 1
Shai
  • 111,146
  • 38
  • 238
  • 371
  • 1
    Does your compiler implement TR1? If so, you can still use `std::tr1::bind`, which is exactly what you need here. – Björn Pollex May 13 '13 at 09:20
  • Any reason why it's not a `static` member function (or just not a member function at all)? That is, is there a specific `A` object you should be using to call `invalidB`? – Joseph Mansfield May 13 '13 at 09:21
  • can you make `InvalidD` static? – Marius Bancila May 13 '13 at 09:23
  • @sftrabbit I need information from a specific instance of `A` to determine if `B` is valid or not. It cannot be static. – Shai May 13 '13 at 09:24
  • use `bind1st` with `mem_fun` or `mem_fun_ref` – PiotrNycz May 13 '13 at 09:25
  • @BjörnPollex Even without TR1, this can be done with a combination of `mem_fun` and `bind1st`. It's complicated enough, however, that it is usually simpler just to write your own functional object. – James Kanze May 13 '13 at 09:26
  • 1
    Oh, I just realised that `someMethod` is a member of `A`. – Joseph Mansfield May 13 '13 at 09:27
  • @JamesKanze - I'm afraid I do not follow you. Can you please be more specific on how `bind1st` and `mem_fun` can help me. I am unable to see how to use them to solve my problem – Shai May 13 '13 at 10:03
  • @Shai You can build up a functional object incrementally. The syntax is unreadable enough that you don't want to know more. – James Kanze May 13 '13 at 10:54

2 Answers2

5

Once you're in remove_if, you've lost the this pointer of A. So you'll have to declare a functional object which holds it, something like:

class IsInvalidB
{
    A const* myOwner;
public:
    IsInvalidB( A const& owner ) : myOwner( owner ) {}
    bool operator()( B const& obj )
    {
        return myOwner->invalidB( obj );
    }
}

Just pass an instance of this to remove_if.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
  • Thanks, but I was kind of hoping to avoid declarations of additional functions/objects... – Shai May 13 '13 at 09:25
  • @Shai You can do it with `mem_fun` and `bind1st`, but I think you'll find that defining the additional object type is simpler. (Having access to `std::bind` or lambdas changes the situation, of course.) – James Kanze May 13 '13 at 09:26
3

If you don't want to create additional functors and you're restricted to C++03, use std::mem_fun_ref and std::bind1st:

std::remove_if(vectorB.begin(), vectorB.end(),
               std::bind1st(std::mem_fun_ref(&A::invalidB), some_A));

Alternatively, if your compiler supports TR1, you can use std::tr1::bind:

using std::tr1::placeholders::_1;
std::remove_if(vectorB.begin(), vectorB.end(),
               std::tr1::bind(&A::invalidB, some_A, _1));
  • I get the following compile error: invalid redeclaration of member function "std::binder1st<_Fn2>::operator()(const std::unary_function<_Fn2::second_argument_type, _Fn2::result_type>::argument_type &) const [with _Fn2=std::const_mem_fun1_ref_t]" – Shai May 13 '13 at 10:19
  • PS - thank you for the answer. still not working, but I'm playing with it. – Shai May 13 '13 at 10:21
  • @Shai: this is a known defect in the standard library, ironically caused by fixing a different defect. This is the reason why `std::[tr1::]bind` was born, really. –  May 13 '13 at 10:33