如何在C ++(STL)中否定一个仿函数?

时间:2008-11-05 14:15:22

标签: algorithm stl c++

我有一些功能可以找到一个值:

struct FindPredicate
{

    FindPredicate(const SomeType& t) : _t(t) {
    }
    bool operator()(SomeType& t) {
      return t == _t;
    }

private:
    const SomeType& _t;
};

bool ContainsValue(std::vector<SomeType>& v, SomeType& valueToFind) {
    return find_if(v.begin(), v.end(), FindPredicate(valueToFind)) != v.end();
}

现在我想编写一个函数来检查向量的所有成员是否满足该谓词:

bool AllSatisfy(std::vector<SomeType>& v) {
    /* ... */
}

一种解决方案是使用std::count_if算法。

有没有人知道一个涉及否定谓词的解决方案?

4 个答案:

答案 0 :(得分:20)

最佳解决方案是使用STL functional library。通过从unary_function<SomeType, bool>派生您的谓词,您就可以使用not1函数,它正是您所需要的(即取消一元谓词)。

以下是如何做到这一点:

struct FindPredicate : public unary_function<SomeType, bool>
{
    FindPredicate(const SomeType& t) : _t(t) {}

    bool operator()(const SomeType& t) const {
      return t == _t;
    }

private:
    const SomeType& _t;
};

bool AllSatisfy(std::vector<SomeType>& v, SomeType& valueToFind)
{
    return find_if(v.begin(), 
                   v.end(), 
                   not1(FindPredicate(valueToFind))) == v.end();
}

如果你想推出自己的解决方案(也就是恕我直言,不是最好的选择...),那么你可以编写另一个谓词,这是对第一个的否定:

struct NotFindPredicate
{

    NotFindPredicate(const SomeType& t) : _t(t) {
    }
    bool operator()(SomeType& t) {
      return t != _t;
    }

private:
    const SomeType& _t;
};

bool AllSatisfy(std::vector<SomeType>& v) {
    return find_if(v.begin(), 
                   v.end(), 
                   NotFindPredicate(valueToFind)) == v.end();
}

或者你可以做得更好并写一个模板函子否定器,如:

template <class Functor>
struct Not
{
    Not(Functor & f) : func(f) {}

    template <typename ArgType>
    bool operator()(ArgType & arg) { return ! func(arg); }

  private:
    Functor & func;
};

您可以使用如下:

bool AllSatisfy(std::vector<SomeType>& v, SomeType& valueToFind)
{
    FindPredicate f(valueToFind);
    return find_if(v.begin(), v.end(), Not<FindPredicate>(f)) == v.end();
}

当然,后一种解决方案更好,因为您可以将 Not 结构重用于您想要的每个仿函数。

答案 1 :(得分:7)

查看std库仿函数not1,它返回一个仿函数,它不是你给它的仿函数返回的逻辑。

您应该可以执行以下操作:

bool AllSatisfy(std::vector<SomeType>& v, SomeType& valueToFind) {
    return find_if(v.begin(), v.end(), not1(FindPredicate(valueToFind))) != v.end();
}

答案 2 :(得分:2)

我第一次使用not1时,我想知道为什么它不是简单地称为not

答案让我感到有些惊讶(见评论)。

答案 3 :(得分:0)

在使用它时,您不需要FindPredicate仿函数,因为在示例中您只是测试相等。

bool all_equal(std::vector<SomeType>& v, SomeType& valueToFind)
{
   return v.end() == find_if(v.begin(), v.end(), std::bind1st (equal_to (), valueToFind) );
}

bool all_not_equal( std::vector<SomeType>& v, SomeType &valueToFind ) {
{
   return v.end() == find_if(v.begin(), v.end(), std::bind1st (not_equal_to (), valueToFind) );
}

你可以自己制作一个模板。

template< typename InputIterator , typename Predicate >
bool test_all( InputIterator first, InputIterator last, Predicate pred )
{
  return last == find_if( first, last, pred );
}

test_all( v.begin(), v.end(), std::bind1st( not_equals_to_( value )) );