2008-11-05 57 views
14

我有一些功能找到一個值:如何取消C++(STL)中的函數?

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

有誰知道涉及否定謂詞的解決方案嗎?

回答

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

當然,後一種解決方案是更好,因爲你可以重複使用結構與你希望每一個函子。

+0

然後像SGI的人確實返回一個不對象,而無需指定它的類型,你可以添加一個墊片模板函數。 – xtofl 2008-11-05 19:55:17

7

查看std庫函子not1,它返回一個函子,它是邏輯的,而不管你給它的函數返回。

你應該能夠做這樣的事情:

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

我第一次用not1我不知道爲什麼它沒有簡單地稱爲not

答案令我感到吃驚(見評論)。

+0

顯然`不'是符號`!`的預留替代表示(標準[lex.key]中的2.11.2節) – Motti 2008-11-05 15:20:11

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