我有一些功能可以找到一个值:
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
算法。
有没有人知道一个涉及否定谓词的解决方案?
答案 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 )) );