Idiomatic C++ for remove_if

Idiomatic C++ for remove_if

本文关键字:if remove for C++ Idiomatic      更新时间:2023-10-16

我有这个类

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不是很熟悉)?

试试这个:

points.erase(std::remove_if(points.begin(), 
                            points.end(),
                            std::not1(std::mem_fun_ref(&Point2D::isValid))), 
             points.end());

不是完全标准的,但几乎:您可以使用boost::bind并执行以下

points.erase( std::remove_if( points.begin(), points.end(),
  !boost::bind(&Point2D::isValid, _1 )), points.end() );

顺便说一下,您应该声明isValid方法const。

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();
  }
};

请注意,这两个函数都是常量。现在您可以实现一个通用的否定函子:

struct negate{
  template<class T>
  bool operator()(T const& t){
    return !t;
  }
};

使用它:

points.erase( std::remove_if( points.begin(), points.end(), negate()), points.end() );

您可以使用std::mem_fun_refstd::not1:的组合来执行您想要的操作

points.erase( std::remove_if( points.begin(), points.end(),
                              std::not1( std::mem_fun_ref( &Point2D::isValid ) ) ),
              points.end() );

值得一提的是,这其中唯一"惯用"的部分是擦除-删除习语。

如果Boost对您来说还可以,请将@Randall-Flagg的建议与boost::remove_erase_if:一起使用

boost::remove_erase_if(points, !boost::bind(&Point2D::isValid, _1));

我想您正在寻找not1

编辑:仔细看你的例子,我认为你不能用任何其他方式来做,因为isValid()是一个成员函数。