6

考虑以下场景:

bool is_odd(int i)
{
    return (i % 2) != 0;  
}
int main()
{
    // ignore the method of vector initialization below.
    // assume C++11 is not to be used.
    std::vector<int> v1 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    std::vector<int> v2 = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
    
    // removes all odd numbers, OK
    v1.erase( std::remove_if(v1.begin(), v1.end(), is_odd), v1.end() );

    // remove all even numbers
    v2.erase( std::remove_if(v2.begin(), v2.end(), ???), v2.end() );
}

我可以使用相同的is_odd()UnaryPredicate 来删除最后一行中预期的偶数吗main()?或者我是否必须写一个is_even(),即使它只是:

bool is_even(int i)
{
    return !is_odd(i);  
}
4

2 回答 2

10

检查std::not1函数。它做你想做的事。

v2.erase( std::remove_if(v2.begin(), v2.end(), std::not1(std::ptr_fun(is_odd))), v2.end() );

活生生的例子

无论如何,如果由我决定加上 C++11 可用,我会更喜欢:

 v2.erase( std::remove_if(v2.begin(), v2.end(), [&](auto/* or the type */ const& item){return !is_odd(item);}), v2.end() );

因为据我记得std::not1以前lambda是有帮助的。

于 2015-12-17T08:39:24.373 回答
5

您可以使用std::not1. 可悲的是,std::not1需要一个具有嵌套argument_typeresult_type类型的函数对象参数。也就是不能直接使用。取而代之的是,std::ptr_fun在将否定器与普通函数一起使用时,需要结合使用 with:

    v2.erase( std::remove_if(v2.begin(), v2.end(), std::not1(std::ptr_fun(is_odd))), v2.end() );

在上次委员会会议上std::not_fn,从图书馆基础 TS 2移到了工作草案中。也就是说,希望使用 C++17 可以为通用否定器提供更好的报价。

通常,当您需要使用任何std::*_fun功能时,乐趣就会停止。正如其他人指出的那样,改用 lambda 可能是合理的:

v2.erase( std::remove_if(v2.begin(), v2.end(), [](auto&& x){ return !::is_odd(x); }), v2.end() );

使用带有inline函数调用运算符的 lambda 函数或函数对象还具有编译器更容易内联代码的优点。

显然,如果您需要在 C++11 之前使用 C++,则std::not1/std::ptr_fun方法是最容易立即使用的,甚至不可能使用 lambda 函数。在这种情况下,您可能希望创建一个简单的函数对象来支持内联:

struct not_odd {
    template <typename T>
    bool operator()(T const& value) const { return !::odd(value); }
};
// ...
v2.erase( std::remove_if(v2.begin(), v2.end(), not_odd()), v2.end() );
于 2015-12-17T08:54:37.960 回答