[C++] Erase-Remove idiom

Hi, I'm trying to delete from a vector all the elements that satisfy a specific property with the Erase-Remove idiom.
So I have a std::vector<MyType> myVector and in the header file I have a member function

1
2
3
bool HasToBeRemovedFromVector(MyType &v) {
	return (/* Here I evaluate the condition */);
}


Then in the source file I do

 
myVector.erase(std::remove_if(myVector.begin(), myVector.end(), std::ptr_fun<MyType, bool>(HasToBeRemovedFromVector), myVector.end());


but it doesn't work. And I can't define my function as static since it has to access some member values.

How can I solve? Which is the correct syntax? Thanks in advance!
1
2
3
bool HasToBeRemovedFromVector(MyType &v) {
	return (/* Here I evaluate the condition */);
}
It does not look as member function. It looks like standatlone function taking a single parameter. How do you call it?
I actually never call it... I just pass it to the remove_if which should use it to evaluate whether the element has to be removed from the vector or not.
But probably you are right about the fact that it is not a member function. I put that code in the header file, within the definition of the class, but maybe this is not correct...

Any suggestions?
Last edited on
If this is just a function, just pass it to algorithm (without using deprecated entities which are going to be deleted from next language revision)
myVector.erase(std::remove_if(myVector.begin(), myVector.end(), HasToBeRemovedFromVector), myVector.end());
To use a member function as the unary predicate, wrap the call with std::bind()
http://en.cppreference.com/w/cpp/utility/functional/bind

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

struct A
{
    bool has_to_be_removed( int a ) const { return a > value ; }

    int value = 10 ;

    std::vector<int> my_vector { 23, 7, 2, 78, 45, 34, 7, 4, 9, 22, 38 } ;

    void test_it()
    {
        for( int v : my_vector ) std::cout << v << ' ' ; std::cout << '\n' ;

        using std::placeholders::_1 ;
        my_vector.erase( std::remove_if( my_vector.begin(), my_vector.end(), 
                                         std::bind( &A::has_to_be_removed, this, _1 ) ),
                         my_vector.end() ) ;

        for( int v : my_vector ) std::cout << v << ' ' ; std::cout << '\n' ;
    }
};

int main()
{
    A a ;
    a.test_it() ;
}

http://coliru.stacked-crooked.com/a/cc241f908a48cd1e
Ok, thank you very much. I was also curious because I have been told that this can be done with std::ptr_fun. Is it true? And in case it is... how? :)
P.S. I can't use C++11 features! :(
Last edited on
1) ptr_fun and others are deprecated and should be avoided. Use std::bind, std::function and lambdas which supersede them
2) ptr_fun is a function object wrapping non-member function:
http://en.cppreference.com/w/cpp/utility/functional/ptr_fun
mem_fun_ref (and others) is a function object wrapping member function:
http://en.cppreference.com/w/cpp/utility/functional/mem_fun_ref
I must be missing something here... I tried

myVector.erase(std::remove_if(myVector.begin(), myVector.end(), std::mem_fun_ref(&MyClass::HasToBeRemovedFromVector)), myVector.end());

and it gives me some errors like


error: no match for call to ‘(std::mem_fun1_t<bool, MyClass, MyClass::MyType&>) (MyClass::MyType&)’


Instead, if I just try to write

 
myVector.erase(std::remove_if(myVector.begin(), myVector.end(), HasToBeRemovedFromVector), myVector.end());


it says


error: cannot convert ‘MyClass::HasToBeRemovedFromVector’ from type ‘bool (MyClass::)(MyClass::MyType&)’ to type ‘bool (MyClass::*)(MyClass::MyType&)’
Last edited on
> I have been told that this can be done with std::ptr_fun. Is it true?

Not with std::ptr_fun. With either std::mem_fun or std::mem_fun_ref, in conjunction with std::bind1st.


> And in case it is... how? :)

Avoid writing fresh code which uses deprecated features. Instead, write a custom binder:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

struct A
{
    bool has_to_be_removed( int a ) const { return a > value ; }
    
    struct binder 
    {
        explicit binder( const A& aa ) : a(aa) {}
        bool operator() ( int v ) const { return a.has_to_be_removed(v) ; }
        const A& a ;
    };

    int value = 10 ;

    std::vector<int> my_vector { 23, 7, 2, 78, 45, 34, 7, 4, 9, 22, 38 } ;

    void test_it()
    {
        for( int v : my_vector ) std::cout << v << ' ' ; std::cout << '\n' ;

        my_vector.erase( std::remove_if( my_vector.begin(), my_vector.end(), binder(*this) ),
                         my_vector.end() ) ;

        for( int v : my_vector ) std::cout << v << ' ' ; std::cout << '\n' ;
    }
};

int main()
{
    A a ;
    a.test_it() ;
}

http://coliru.stacked-crooked.com/a/60c6a68aaeac30b3
Last edited on
So, to recap... I tried

 
myVector.erase(std::remove_if(myVector.begin(), myVector.end(), std::mem_fun_ref(&MyClass::HasToBeRemovedFromVector)), myVector.end());


and it gives me some errors like


error: no match for call to ‘(std::mem_fun1_t<bool, MyClass, MyClass::MyType&>) (MyClass::MyType&)’


Instead, if I just try to write

 
myVector.erase(std::remove_if(myVector.begin(), myVector.end(), HasToBeRemovedFromVector), myVector.end());


it says


error: cannot convert ‘MyClass::HasToBeRemovedFromVector’ from type ‘bool (MyClass::)(MyClass::MyType&)’ to type ‘bool (MyClass::*)(MyClass::MyType&)’


Finally if I use

 
myVector.erase(std::remove_if(myVector.begin(), myVector.end(), &HasToBeRemovedFromVector), myVector.end());


it tells me strange things like


must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘__pred (...)’, e.g. ‘(... ->* __pred) (...)’


Nothing "simple" seems to work... Is it possible?
Last edited on
> Is it possible?

Deprecated is defined by the IS as: Normative for the current edition of the Standard, but not guaranteed to be part of the Standard in future revisions.

As such, it sends a clear message to programmers: Do not use this feature anymore in any new code that you write. However if you already have legacy code that uses this feature, you have time to fix it: it will continue to work as it did before at least till the next revision of the standard.
http://www.cplusplus.com/forum/general/62326/#msg337457


It is currently possible; and it will continue to be possible for another two years.
After which it will no longer be part of standard C++.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>

struct A
{
    bool has_to_be_removed( int a ) const { return a > value ; }
    
    int value = 10 ;

    std::vector<int> my_vector { 23, 7, 2, 78, 45, 34, 7, 4, 9, 22, 38 } ;

    void test_it()
    {
        for( int v : my_vector ) std::cout << v << ' ' ; std::cout << '\n' ;

        my_vector.erase( std::remove_if( my_vector.begin(), my_vector.end(), 
                                         std::bind1st( std::mem_fun_ref(&A::has_to_be_removed), *this ) ),
                         my_vector.end() ) ;

        for( int v : my_vector ) std::cout << v << ' ' ; std::cout << '\n' ;
    }
};

int main()
{
    A a ;
    a.test_it() ;
}

http://coliru.stacked-crooked.com/a/5afc50807860b5e0
I know this is becoming more and more annoying but this does not work either.
It complains about the


use of deleted function ...


I am starting to think about giving up and creating a temporary vector in which to store all the objects that must be preserved. Then a swap and it's done.

Anyway I would have liked to understand this other method with the remove_if, but it is starting to seem unlikely...
Post your exact code. HasToBeRemovedFromVector , class it is in and where do you need it.

And show how you would use it other way. I still think that there is something about it or the way you are using it, which will require modifications to posted code.
I know it's weird but I can't post the exact code... The reason is that it is proprietary code (not mine, of course) and I do not have the authorization to release any part of it. I thought it was just something silly about the syntax, but it seems a bit more complicated. Nevermind: I will use a temporary vector and a swap.
Last edited on
Topic archived. No new replies allowed.