我有这个班级
class Point2D
{
public:
bool isValid();
// ...
private:
double x_, y_;
};
我有一个std::vector< Point2D >
,我想删除无效点,现在我喜欢这样:
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
}
是否有一种标准的方法(精美),例如,不需要“复制”类方法Point2D::isValid
的功能?
也许使用C ++ 11 lambda(我对lambda不是很熟悉)?
答案 0 :(得分:16)
试试这个:
points.erase(std::remove_if(points.begin(),
points.end(),
std::not1(std::mem_fun_ref(&Point2D::isValid))),
points.end());
答案 1 :(得分:11)
不是完全标准但几乎:你可以使用boost :: bind并执行以下操作
points.erase( std::remove_if( points.begin(), points.end(),
!boost::bind(&Point2D::isValid, _1 )), points.end() );
顺便说一下,你应该声明isValid方法const。
答案 2 :(得分:10)
lambda版本也不会更干净,但它还有另一个重要优势: locality 。您会看到使用它的代码:
points.erase( std::remove_if( points.begin(), points.end(),
[](const Point2D& p){
return !p.isValid();
}), points.end() );
注意,您需要更改isValid
以使其成为const
函数,否则您无法在引用到const(const Point2D&
)上调用它。 />
另一种选择是为您的班级实施operator!
:
class Point2D{
// ... as before
public:
bool isValid() const;
bool operator!() const{
return !isValid();
}
};
注意,两个函数都是const。现在你可以实现一个通用的否定函子:
struct negate{
template<class T>
bool operator()(T const& t){
return !t;
}
};
并使用:
points.erase( std::remove_if( points.begin(), points.end(), negate()), points.end() );
答案 3 :(得分:6)
您可以使用std::mem_fun_ref
和std::not1
的组合来执行您想要的操作:
points.erase( std::remove_if( points.begin(), points.end(),
std::not1( std::mem_fun_ref( &Point2D::isValid ) ) ),
points.end() );
对于它的价值,唯一的“惯用”部分是erase-remove idiom。
答案 4 :(得分:5)
如果Boost适合您,请使用@Randall Flagg与boost::remove_erase_if
一起提出的内容:
boost::remove_erase_if(points, !boost::bind(&Point2D::isValid, _1));
答案 5 :(得分:2)
我认为您正在寻找not1
编辑:仔细观察你的例子,我认为你不能以任何其他方式做到这一点,因为isValid()
是一个成员函数。