STL源碼分析--functional

更多精彩內容,請關注微信公衆號:後端技術小屋後端

1 相關頭文件

functional
functional.h
stl_function.h

2 一元函數對象

一元函數對象,是指這類函數對象只接受一個參數並返回一個參數。微信

unary_function爲STL中全部一元函數對象的基類。它定義了一元函數對象的輸入/輸出參數類型,其中argument_type爲輸入參數類型,result_type爲輸出參數類型,這兩種類型由輸入模板參數推導而來。less

template <class _Arg, class _Result>
struct unary_function {
  typedef _Arg argument_type;
  typedef _Result result_type;
};

下面介紹幾種有意思的一元函數對象。ide

2.1 binder1st/binder2nd

binder1st的功能:將某個參數值綁定到可調用對象(Callable type,函數對象/函數指針/std::function)的第一個參數中。同理,binder2nd將某個參數值綁定到可調用對象的第二個參數中。函數

有了binder1st/binder2nd,即可利用已有的可調用對象生成各類變體,避免了從新定義帶來的代碼冗餘。源碼分析

auto f = [](double a, double b){ return 2*(a+b); };
    double a0 = 1.0;
    double b0 = 2.0;
    auto uf1 = std::binder1st(f, a0);
    auto uf2 = std::binder2nd(f, b0);
    
    std::cout << uf1(3.0) << std::endl; // 執行f函數,參數1:被綁定的a0, 參數2: 3.0
    std::cout << uf2(4.0) << std::endl; // 執行f函數,參數1: 4.0,      參數2:被綁定的b0

binder1st內部嵌套了一個可調用對象op。生成binder1st對象時,其內部記錄傳入的可調用對象和綁定參數。當執行operator()時,其調用可調用對象並返回結果。指針

template <class _Operation> 
class binder1st
  : public unary_function<typename _Operation::second_argument_type,
                          typename _Operation::result_type> {
protected:
  _Operation op;
  typename _Operation::first_argument_type value;
public:
  binder1st(const _Operation& __x,
            const typename _Operation::first_argument_type& __y)
      : op(__x), value(__y) {}
  typename _Operation::result_type
  operator()(const typename _Operation::second_argument_type& __x) const {
    return op(value, __x); 
  }
};

2.2 unary_compose

將兩個屬於unary_function的函數對象級聯。假設函數對象分別爲op1op2, 那麼unary_compose的執行結果爲op1(op2(x))code

所以unary_compose的輸入參數類型爲_Operation2::argument_type,輸出參數類型爲_Operation1::result_type。而且要求在類型上_Operation2::result_type可隱式轉換成_Operation1::argument_type對象

template <class _Operation1, class _Operation2>
class unary_compose
  : public unary_function<typename _Operation2::argument_type,
                          typename _Operation1::result_type> 
{
protected:
  _Operation1 _M_fn1;
  _Operation2 _M_fn2;
public:
  unary_compose(const _Operation1& __x, const _Operation2& __y) 
    : _M_fn1(__x), _M_fn2(__y) {}
  typename _Operation1::result_type
  operator()(const typename _Operation2::argument_type& __x) const {
    return _M_fn1(_M_fn2(__x));
  }
};

2.3 pointer_to_unary_function

將一個指向一元函數的指針封裝成一元函數對象。繼承

template <class _Arg, class _Result>
class pointer_to_unary_function : public unary_function<_Arg, _Result> {
protected:
  _Result (*_M_ptr)(_Arg);
public:
  pointer_to_unary_function() {}
  explicit pointer_to_unary_function(_Result (*__x)(_Arg)) : _M_ptr(__x) {}
  _Result operator()(_Arg __x) const { return _M_ptr(__x); }
};

2.4 mem_fun_t

將類內非靜態成員函數封裝成一元函數對象。

對於mem_fun_t對象,其構造時記錄指向類_Tp內非靜態成員函數(輸入參數個數爲零)的指針,執行時,傳入指向_Tp對象的指針__p,調用(__p->*_M_f)()

在C++中,函數指針相似這種形式:int (*f)(int, double)f指向一個入參爲int, double,出參爲int的函數。調用函數指針f時,只需指定輸入參數。

而成員函數指針相似於:int (T::*mf)(int, double)mf指向一個入參爲int, double, 出參爲int的成員函數。調用成員函數指針時,除了需指定輸入參數外,還需指定T對象指針,由於類中非靜態成員函數是和該類對象綁定的。

template <class _Ret, class _Tp>
class mem_fun_t : public unary_function<_Tp*,_Ret> {
public:
  explicit mem_fun_t(_Ret (_Tp::*__pf)()) : _M_f(__pf) {}
  _Ret operator()(_Tp* __p) const { return (__p->*_M_f)(); }
private:
  _Ret (_Tp::*_M_f)();
};

其餘變體:

  • const_mem_fun_t: 將類內非靜態的const成員函數封裝成一元函數對象
  • mem_fun_ref_t: 相似mem_fun_t,區別在於調用mem_fun_t時傳入的是類對象指針,而調用mem_fun_ref_t時傳入的是類對象引用。
  • const_mem_fun_ref_t: const_mem_fun_tmem_fun_ref_t的組合

2.5 其餘

  • negate: 取負操做。實現中對_Tp對象執行operator-操做,所以negate的輸入模板參數不止爲數字,也但是重載了operator-操做符的其餘任何類型。
  • logical_not: 邏輯取反。函數對象輸入參數類型爲_Tp, 輸出參數類型爲bool。實現中對_Tp對象執行operator!操做,對象可重載該操做符。
  • unary_negate: 同negate類似,只不過帶了一個判斷條件。輸入參數__x, 返回布爾值!_M_pred(__x)

3 二元函數對象

二元函數對象接受兩個參數,返回一個結果值。

STL中定義的全部二元函數對象都繼承自binary_function, 其中

  • first_argument_type: 第一個輸入參數類型
  • second_argument_type: 第二個輸入參數類型
  • 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;
};

3.1 mem_fun1_t

mem_fun_t相似,將一個成員函數指針封裝成函數對象。區別在於mem_fun_t中成員函數入參個數爲零,而mem_fun1_t中成員函數入參個數爲1,這樣的話調用mem_fun1_t時,需同時傳入成員函數的入參和成員函數所在類對象指針。

其餘變體:const_mem_fun1_t/mem_fun1_ref_t/const_mem_fun1_ref_t,功能與mem_fun_t的變體相似,這裏跳過

3.2 其餘

如下二元函數對象顧名思義,本質上是對各類操做符的封裝。

plus
minus
multiplies
divides
modulus
equal_to
not_equal_to
greater
less
greater_equal
less_equal
logical_and
logical_or
logical_not

binary_compose: 功能同unary_compose。區別在於將三個二元函數對象級聯,輸出__fn1(__fn2(__x), __fn3(__x))

推薦閱讀

更多精彩內容,請掃碼關注微信公衆號:後端技術小屋。若是以爲文章對你有幫助的話,請多多分享、轉發、在看。
二維碼

相關文章
相關標籤/搜索