C++11綁定器bind及function機制( 二 )

find_if返回指向65元素的迭代器:
file:///Users/guochen/Notes/docs/media/16656563650484/16657214749366.jpg

C++11綁定器bind及function機制

文章插圖
以上就是綁定器的概念 。因此需要綁定器的原因就很明顯了,綁定器可以返回一個轉換后的某元函數對象 , 用于匹配泛型算法 。
根據上面的理解 , 接下來實現一下bind1st , 代碼實現如下:
/*可以看到 自己實現的綁定器本質上也是個函數對象 調用operator()進行綁定*/template<typename Compare, typename T>class _mybind1st {public:_mybind1st(Compare comp, T first) : _comp(comp), _val(first) {}bool operator()(const T &second) {return _comp(_val, second);}private:Compare _comp;T _val;};/*實現bind1st 函數模板*///直接使用函數模板,好處是可以進行類型推演template<typename Compare, typename T>_mybind1st<Compare, T> mybind1st(Compare comp, const T &val) { //綁定器返回值_mybind1st為一元函數對象return _mybind1st<Compare, T>(comp, val);}上述代碼中mybind1st綁定器第一個參數Compare comp是要綁定的二元函數對象,第二個參數val是在原有函數對象上綁定的值,最后綁定器調用_mybind1st模板函數對象的小括號運算符重載并返回該一元匿名函數對象,可以看到_mybind1st小括號運算符重載中已將綁定器mybind1st第二個參數val傳遞給了原本的二元函數對象Compare comp,因此原本綁定器接收的二元函數對象只需要處理第二個參數 。所以綁定器返回的函數對象_mybind1st其實是在原本的函數對象上套了一層參數的新的函數對象,閱讀上面的代碼實現 , 就可更深刻的理解bind1st的底層原理 。
與此同時 , 不難寫出bind2nd的實現,顧名思義該綁定器是對第二個參數進行綁定 , 不過多贅述,貼出實現代碼:
template<typename Compare, typename T>class _mybind2nd {public:_mybind2nd(Compare comp, T second) : _comp(comp), _val(second) {}bool operator()(const T &first) {return _comp(first, _val);}private:Compare _comp;T _val;};template<typename Compare, typename T>_mybind2nd<Compare, T> mybind2nd(Compare comp, const T &val) {return _mybind2nd<Compare, T>(comp, val);}根據上文,我們清楚了解到泛型算法find_if第三個參數接收一元函數對象,且該泛型算法功能是尋找第一個符合某條件的元素,我們對其補充實現,代碼貼出:
/** * 自己實現了find_if后發現其實綁定器返回的就是綁定后的函數對象 * 使用綁定器的目的:就是將原本某元的函數對象轉化為另一個元的函數對象 * 說白了,綁定器還是對函數對象的一個應用 **/template<typename Iterator, typename Compare>Iterator my_find_if(Iterator first, Iterator last, Compare comp) {for(; first != last; ++first) {if(comp(*first)) { //調用comp的小括號運算符重載 一元函數對象 comp.operator()(*first)return first;}}return last;}此時要尋找vector中第一個小于70的數,就可以這樣寫:
auto it = my_find_if(vec.begin(), vec.end(), mybind1st(greater<int>(), 70));cout << *it << endl; //打印vec中第一個小于70的數值以上 , 圍繞bind1st、bind2nd以及函數對象等,展開討論了綁定器bind1stbind2nd的實現原理,但是同時我們也發現其缺點,就是只能對二元函數對象進行綁定轉換,讓其轉換為一元函數對象,那如果遇到很多元的函數對象,我們還得一個一個自己去實現嗎?所以將boost庫的boost::bind引入到了C++11標準庫中,接下來我們介紹C++11的綁定器std::bind , 它是對上述兩種綁定器的泛化 。支持任意函數對象(其實標準庫中最多支持29元函數對象 , 不過這也足夠使用了) 。
補充:上面都是以函數對象為例,作為綁定器第一個參數傳遞 , 其實第一個參數可以是函數對象、成員函數、也可以是普通函數 。
總結:綁定器本身是函數模板,綁定器第一個參數可能是普通函數、成員函數或函數對象等,返回的一定是函數對象 。還有就是這兩個綁定器在C++17中已移除,因此僅用于學習和理解綁定器 , 也方便我們對C++11引入的bind的學習 。至于當前這兩個綁定器如何實現對類成員函數的綁定等等我們也沒必要去尋找答案了(我一開始也在努力尋找如何使用這兩個綁定器去綁定類成員函數 , 但是發現

推薦閱讀