2012-08-04 22 views
9

我只是read有人撥打一類具有一個構造函數和一個operator()一個謂詞Predicate和Functor有什麼區別?

// Example 
class Foo { 
    public: 
    Foo(Bar); 
    bool operator()(Baz); 
    private: 
    Bar bar; 
}; 

不過,我還沒有聽說過這個詞謂語而在這種情況下之前使用。我會打電話給函數。對我而言,謂詞將是形式邏輯領域的一些東西。

這就提出了以下問題:

  • 這是類似的東西Foo一個共同的詞嗎?
  • 這兩個術語是否可以互換使用,還是說它們的意思稍有不同?
  • 或者
    • 是否返回類型(bool對別的東西)有什麼關係呢?
    • 怎麼樣operator()const

回答

22

函子是指支持表達式中的運算符()的實體(具有零個或多個參數),即在語法上表現爲函數的某個術語。 Functor不一定是某個班的對象,其重載operator()。普通的函數名稱也是仿函數。儘管在某些情況下,您可以看到術語「仿函數」用於更狹窄和排他的意義上:只是類對象,而不是普通函數。

謂詞特定種類的仿函數:計算結果爲布爾值的函子。它不一定是bool類型的值,而是具有「布爾」語義的任何類型的值。儘管如此,該類型應該可以隱式轉換爲bool

+3

不錯。在一般意義上,仿函數是*任何表示設計函數的對象/神器。無論是在語法上還是/或者操作符()都是糖。 – 2012-08-04 04:31:07

3

所示出的類是實現謂詞函子。

A predicate是一個布爾函數。

關於operator()這裏是非const:理想情況下應該是const,是的。

+0

顯示的類是一個例子。我想知道是否每個謂詞都是一個函子。什麼限制適用,除了返回值是布爾值?返回'bool'的自由函數是否也是一個謂詞? – bitmask 2012-08-04 03:37:36

+0

每個謂詞都是一個布爾函數,在某個適當的抽象層次上。在Prolog中,當然謂詞不是C++函子:-)。所以是的,一個獨立的函數可以被用作謂詞。看看你鏈接到的問題(對不起,我沒看過),它不是一個純粹的謂詞,因爲它有副作用。理想情況下謂詞沒有副作用,它只是告訴你參數是否滿足某些條件,通常它們有一些關係。 – 2012-08-04 03:41:59

2

謂詞是一種特殊的函數對象。見Nicolai Josuttis的優秀column。引用:

返回布爾值的函數對象是謂詞。這就是 幾乎所有的教程,書籍和手冊都寫了關於STL謂詞 的書。然而,這不是全部。

然而,存在這不幸不 在任何手動或在C++標準中提到的附加要求:謂詞應 總是返回相同的結果爲相同的值。

或者,在C++語言:你應該申報經營者()作爲 常量成員函數(而不是與可變玩遊戲或管型)。 出於同樣的原因,謂詞的副本應該與原始版本具有相同的狀態 。

原因是STL算法會複製周圍的函數對象,並且複製不應該影響應用函數對象的結果。

template<typename Arg0> 
struct UnaryPredicate 
: 
    public std::function<bool(Arg0 const&)> 
{ 
    bool operator()(Arg0 const& a0) const 
    { 
     return // your code here 
    } 
}; 

template<typename Arg0, typename Arg1> 
struct BinaryPredicate 
: 
    public std::function<bool(Arg0 const&, Arg1 const&)> 
{ 
    bool operator()(Arg const& a0, Arg const& a1) const 
    { 
     return // your code here 
    } 
}; 
1

如前所述,謂詞只是一個用戶提供的指令,用於將某些事物分析爲布爾狀態。所以,你可以有相同的兩件事情做同樣的事情......

struct is_odd 
{ 
    is_odd() : count(0); 
    bool operartor() (int i) const { ++count; return (i % 2) == 1; } 

private 
    int count; 
} 

而且......

bool isOdd(int i) { return (i % 2) == 1; } 

那麼,什麼特別之處函子?它保持狀態,如果你想要它!這意味着,而這兩行代碼做同樣的事情(假設v是一個向量,其值0 - 9)...

for_each(v.begin(), v.end(), isOdd); //using C-style function pointer 

而且......

is_odd fn = for_each(v.begin(), v.end(), is_odd); //using functor 

只有第二個用例可以您再調用...

int calls = fn.count; 

這是因爲的for_each(以及其他STL算法函數)返回它在最後使用的仿函數,所以現在的最終狀態可以查詢。

另一件很酷的事情要注意的是,在第二種情況下,我們使用的是所謂的「匿名」對象。