C++之函式物件/偽函式(Function Object)詳解(二)
阿新 • • 發佈:2019-01-29
除了自定義的函式物件,標準庫還為我們提供了一系列現成的函式物件, 比如常見的數學、邏輯運算等。例如:negate<type>(),plus<type>(),minus<type>(),multiplies<type>(),divides<type>(),modulus<type>(),equal_to<type>,greater<type>(),less<type>(),logical_not<type>(),logical_and<type>(),等等。
關於函式物件的最後一個很重要的概念是“函式介面卡”。函式介面卡,本質上講也是一個函式物件。這個函式物件通過將一個或多個函式物件或者特定的資料按一定規則組合起來,以完成某些特定的功能。標準庫為我們提供了幾種函式介面卡,例如:通過bind1st和bind2nd兩個包裝函式即可返回相應的介面卡,這兩個函式各有兩個形參,分別為二元函式物件和一個數值,介面卡自動把數值賦給函式物件的第1個(bind1st)或第2個(bind2nd)引數,並返回一個一元的函式物件。例如以下語句:
注意:不要誤把bind1st和bind2nd當成是函式介面卡,它們僅僅是兩個普通的包裝函式模板,它們返回的才是真正的函式介面卡。對應的函式物件型別分別為binder1st和binder2nd。這兩個函式模板實現如下所示:
除了這兩個函式介面卡,標準庫中還定義了兩個"取反器",分別可以通過呼叫輔助函式not1和not2來獲得,即unary_negate<type>和binary_negate<type>。此外,包裝函式模板mem_func_ref返回的介面卡用於自動呼叫物件的成員函式,具體細節及其他介面卡可以到C++參考網站檢視。
函式介面卡是C++中一個強有力的工具,它允許我們針對多個函式物件按照需要進行任意組合,來產生意義豐富的表示式。這種方法被稱為"function composition"。比如對於函式f(x),g(x),h(x,y),對他們進行組合,可以生成f(g(x)),g(f(x)),h(f(x),g(x))等複雜的函式。這裡f,g分別對應了一元函式物件,h對應了二元函式物件,組合函式可以認為是函式介面卡。
不幸的是,標準庫並沒有給我們提供太多的介面卡。因此,想要很好地利用它,還需要我們自己來定義。我們已經知道,自定義函式物件是件很容易的事情,但是想要讓函式物件能在介面卡中進行組合,則需要額外的一些工作。為了方便我們建立能在介面卡中運用的函式物件,標準庫定義了兩個有用的結構,分別為:
最後,我們通過自定義一個函式介面卡來結束本文。要實現的功能為: h(f(x),g(x))。首先這是個一元的函式物件,只接受一個引數x,它組合了三個函式物件H,F,G。可以這樣來實現:
關於函式物件的最後一個很重要的概念是“函式介面卡”。函式介面卡,本質上講也是一個函式物件。這個函式物件通過將一個或多個函式物件或者特定的資料按一定規則組合起來,以完成某些特定的功能。標準庫為我們提供了幾種函式介面卡,例如:通過bind1st和bind2nd兩個包裝函式即可返回相應的介面卡,這兩個函式各有兩個形參,分別為二元函式物件和一個數值,介面卡自動把數值賦給函式物件的第1個(bind1st)或第2個(bind2nd)引數,並返回一個一元的函式物件。例如以下語句:
-
find_if(vec.begin(),vec.end(),bind2nd(modulus<int>(),2));
注意:不要誤把bind1st和bind2nd當成是函式介面卡,它們僅僅是兩個普通的包裝函式模板,它們返回的才是真正的函式介面卡。對應的函式物件型別分別為binder1st和binder2nd。這兩個函式模板實現如下所示:
- template<typename Operation,typename T>
-
binder1st bind1st(const Operation &op,
- {
- return binder1st<Operation>(op,typename Operation::first_argument_type(t));
- }
- template<typename Operation,typename T>
- binder1st bind2nd(const Operation &op, const T &t)
- {
- return binder2nd<Operation>(op,typename Operation::second_argument_type(t));
- }
除了這兩個函式介面卡,標準庫中還定義了兩個"取反器",分別可以通過呼叫輔助函式not1和not2來獲得,即unary_negate<type>和binary_negate<type>。此外,包裝函式模板mem_func_ref返回的介面卡用於自動呼叫物件的成員函式,具體細節及其他介面卡可以到C++參考網站檢視。
函式介面卡是C++中一個強有力的工具,它允許我們針對多個函式物件按照需要進行任意組合,來產生意義豐富的表示式。這種方法被稱為"function composition"。比如對於函式f(x),g(x),h(x,y),對他們進行組合,可以生成f(g(x)),g(f(x)),h(f(x),g(x))等複雜的函式。這裡f,g分別對應了一元函式物件,h對應了二元函式物件,組合函式可以認為是函式介面卡。
不幸的是,標準庫並沒有給我們提供太多的介面卡。因此,想要很好地利用它,還需要我們自己來定義。我們已經知道,自定義函式物件是件很容易的事情,但是想要讓函式物件能在介面卡中進行組合,則需要額外的一些工作。為了方便我們建立能在介面卡中運用的函式物件,標準庫定義了兩個有用的結構,分別為:
- template <class Arg, class Result>
- struct unary_function
- {
- typedef Arg argument_type;
- typedef Result result_type;
- };
- template <class Arg1, class Arg2, class Result>
- struct binary_function
- {
- typedef Arg1 first_argument_type;
- typedef Arg2 second_argument_type;
- typedef Result result_type;
- };
- template<class Operation>
- class binder1st: public unary_function<typename Operation::second_argument_type, typename Operation::return_type>
- {
- public:
- binder1st(const Operation &op, consttypename Operation::first_argument_type &arg): operation(op),arg_1st(arg) {}
- typename Operation::return_type operator() (consttypename Operation::second_argument_type &arg_2nd) const
- {
- return operation(arg_1st,arg_2nd);
- }
- private:
- Operation operation;
- typename Operation::first_argument_type arg_1st;
- };
- template<typename T1, typename T2>
- class Pow: public binary_function<T1,T2,T1>
- {
- public:
- T1 operator() (T1 base, T2 exp) const
- {
- return std::pow(base,exp);
- }
- };
最後,我們通過自定義一個函式介面卡來結束本文。要實現的功能為: h(f(x),g(x))。首先這是個一元的函式物件,只接受一個引數x,它組合了三個函式物件H,F,G。可以這樣來實現:
- template<typename H,typename F,typename G>
- class MyAdapter: unary_function<typename F::argument_type, typename H::return_type>
- {
- public:
- MyAdapter(const H &h, const F &f, const G &g):m_h(h),m_f(f),m_g(g) {}
- typename H::return_type operator() (consttypename F::argument_type &x) const
- {
- return m_h(m_f(x),m_g(x));
- }
- private:
- H m_h;
- F m_f;
- G m_g;
- };