std::bind技術內幕

來源:互聯網
上載者:User

引子

最近群裡比較熱鬧,大家都在山寨c++11的std::bind,三位童孩分別實現了自己的bind,代碼分別在這裡:

木頭雲的實現:串連稍後補上。

mr.li的實現:https://code.google.com/p/y-code-svn/source/browse/

null的實現:http://www.cnblogs.com/xusd-null/p/3693817.html

這些實現思路和ms stl的std::bind的實現思路是差不多的,只是在實現的細節上有些不同。個人覺得木頭雲的實現更簡潔,本文中的簡單實現也是基於木頭雲的bind之上的,在此表示感謝。下面我們來分析一下bind的基本原理。

bind的基本原理

bind的思想實際上是一種延遲計算的思想,將可調用對象儲存起來,然後在需要的時候再調用。而且這種綁定是非常靈活的,不論是普通函數、函數對象、還是成員函數都可以綁定,而且其參數可以支援預留位置,比如你可以這樣綁定一個二元函數auto f = bind(&func, _1, _2);,調用的時候通過f(1,2)實現調用。關於bind的用法更多的介紹可以參考我部落格中介紹:http://www.cnblogs.com/qicosmos/p/3302144.html。

要實現一個bind需要解決兩個問題,第一個是儲存可調用對象及其形參,第二個是如何?調用。下面來分析如何解決這兩個問題。

儲存可調用對象

實現bind的首先要解決的問題是如何將可調用對象儲存起來,以便在後面調用。要儲存可調用對象,需要儲存兩個東西,一個是可調用對象的執行個體,另一個是可調用對象的形參。儲存可調用對象的執行個體相很簡單,因為bind時直接要傳這個可調用對象的,將其作為一個成員變數即可。而儲存可調用對象的形參就麻煩一點,因為這個形參是變參,不能直接將變參作為成員變數。如果要儲存變參的話,我們需要用tuple來將變參儲存起來。

可調用對象的執行

bind的形參因為是變參,可以是0個,也可能是多個,大部分情況下是預留位置,還有可能預留位置和實參都有。正是由於bind綁定的靈活性,導致我們不得不在調用的時候需要找出哪些是預留位置,哪些是實參。如果某個一參數是實參我們就不處理,如果是預留位置,我們就要將這個預留位置替換為對應的實參。比如我們綁定了一個三元函數:auto f = bind(&func, _1, 2, _2);調用時f(1,3);由於綁定時有三個參數,一個實參,兩個預留位置,調用時傳入了兩個實參,這時我們就要將佔位符_1替換為實參1,預留位置_2替換為實參3。這個預留位置的替換需要按照調用實參的順序來替換,如果調用時的實參個數比預留位置要多,則忽略多餘的實參。

調用的實參,我們也會先將其轉換為tuple,用於在後面去替換預留位置時,選取合適的實參。

bind實現的關鍵技術

將tuple展開為變參

前面講到綁定可調用對象時,將可調用對象的形參(可能含預留位置)儲存起來,儲存到tuple中了。到了調用階段,我們就要反過來將tuple展開為可變參數,因為這個可變參數才是可調用對象的形參,否則就無法實現調用了。這裡我們會藉助於一個整形序列來將tuple變為可變參數,在展開tuple的過程中我們還需要根據預留位置來選擇合適實參,即預留位置要替換為調用實參。

相關文章

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。