Reputation: 18665
I have this class
class Point2D
{
public:
bool isValid();
// ...
private:
double x_, y_;
};
I have a std::vector< Point2D >
and I would like to remove the invalid points, now I do like this:
bool invalid ( const Point2D& p )
{
return !p.isValid();
}
void f()
{
std::vector< Point2D > points;
// fill points
points.erase( std::remove_if( points.begin(), points.end(), invalid ), points.end() );
// use valid points
}
Is there a standard way of doing this (beautifully), for example without the need of "duplicating" the functionality of the class method Point2D::isValid
?
Maybe using C++11 lambda (I am not very familiar with lambda)?
Upvotes: 10
Views: 4828
Reputation: 72489
If Boost is OK for you, use what @Randall Flagg suggested together with boost::remove_erase_if
:
boost::remove_erase_if(points, !boost::bind(&Point2D::isValid, _1));
Upvotes: 5
Reputation: 131799
The lambda version won't be any cleaner either, but it has another important advantage: locality. You see the code where you use it:
points.erase( std::remove_if( points.begin(), points.end(),
[](const Point2D& p){
return !p.isValid();
}), points.end() );
Note, that you need to change isValid
to make it a const
function, otherwise you can't call it on a reference-to-const (const Point2D&
).
Another option would be to implement operator!
for your class:
class Point2D{
// ... as before
public:
bool isValid() const;
bool operator!() const{
return !isValid();
}
};
Note, both functions are const. Now you could implement a generic negating functor:
struct negate{
template<class T>
bool operator()(T const& t){
return !t;
}
};
And use that:
points.erase( std::remove_if( points.begin(), points.end(), negate()), points.end() );
Upvotes: 10
Reputation: 94339
You can do what you want using a combination of std::mem_fun_ref
and std::not1
:
points.erase( std::remove_if( points.begin(), points.end(),
std::not1( std::mem_fun_ref( &Point2D::isValid ) ) ),
points.end() );
For what it's worth, the only "idiomatic" part about this is the erase-remove idiom.
Upvotes: 6
Reputation: 119877
Try this:
points.erase(std::remove_if(points.begin(),
points.end(),
std::not1(std::mem_fun_ref(&Point2D::isValid))),
points.end());
Upvotes: 16
Reputation: 320
Not totally standard but nearly : you can use boost::bind and do the following
points.erase( std::remove_if( points.begin(), points.end(),
!boost::bind(&Point2D::isValid, _1 )), points.end() );
By the way you should declare the isValid method const.
Upvotes: 11