標籤:

boost或C++11中的bind怎麼自己實現?

我其實就是看不懂源碼,想問一問。看得人頭疼,真的好難啊。。。

其實就是泛型化函數對象。

在C++99的老標準中,沒有變長模板參數這個特性,所以boost很暴力的重載了從0到9個函數參數數量。

說的具體點,boost中的bind在實現時,在C++99的標準下主要使用了bind_t這個模板類。bind本身只是一個普通類,內部有一個模板類,而模板類bind_t有從1到9這樣多個模板參數數量的重載,當bind進行構造的時候自動選取對應函數參數數量的bind_t。然後又使用了一個listN模板類作為函數的參數列表存儲區,比如list0是沒有參數的函數,list1是有一個參數的函數參數,一直到list9。

但是。。。還是有很多細節不明白,求講解。


現在有variadic template argument了,這個事情會比以前簡單許多,不要去想以前的事情了。


簡單說一下. 不涉及細節.

重要的事情放第一位: bind 已經過時, 請用 lambda.

首先明確: bind 分兩步,

第一步: 調用 bind, 返回一個 functor 對象

auto bar = bind(foo, _1, 2.0);

第二步: 調用 functor 對象, 做類型匹配, 生成對應的 函數調用語句

第三步: 傳遞參數, 調用函數

bar(1);

二三步是一條語句, 但 2 指編譯時, 3 發生在運行時.

第一步

函數原型保存

bind 返回的是一個 functor. 接受的是 Callable.

C++ 里的 "Callable" 被定義為:C++ concepts: Callable ,重點看 INVOKE, 凡是可以被 INVOKE 使用的, 都被稱為 Callable. 一共五種情況, 使用 SFINAE 做 resolution. 詳見鏈接.

所以首先把這個 Callable 存起來. 存一份拷貝.

參數保存

參數使用 tuple 保存, 可能的實現是:

bind_functor(F f, Args... args)
:m_f(f), m_bound_args(std::forward(Args)(args)...)
{}

這裡不對參數做處理. placeholder 啊 類型不匹配啊參數數量不對啊統統不管. 因為壓根管不了.

做個約定, bind_functor 指 bind 返回的 functor 對象, m_f 是 bind_functor 保存的 Callable, m_bound_args 指保存的 "形參". m 打頭的都是成員變數辣

第二步

第二步要調用 生成的 functor 了.

bar(1);

這裡實參出現了, 所以在這一步做類型匹配, placeholder 填入.

首先是 tuple 到函數參數的轉換, c++ - How do I expand a tuple into variadic template function"s arguments? 看這個好了.

但 bind 做的事情還要多一些, 它要確定實參類型, 如果是 placeholder 的怎麼怎麼樣, 是另一個 bind expression 的怎麼怎麼樣. 具體細節看這裡 std::bind - cppreference.com Member function operator() 一節.

要多做的工作也能通過 tuple 和模板搞定. 不細說了.

到第二步, 類型決議已經完成, 最終會在 bind_functor::operator() 內編譯期生成一個對 m_f 的調用:

原先的代碼是這樣的:

operator()(Args...args) {
INVOKE(m_f, do_some_thing&(args)...);
}

通過模板實例化, INVOKE 變成了

m_f(arg1, arg2, ...);

第三步

調用. 因為 arg1, arg2... 的都在運行時才能知道(強調一下類型在第二步已經知道了).

------------------------------

PS: 在 03 時代, 所有 variadic template 的使用以及 tuple 都可以用窮舉法模擬. 比如

template &
tuple;

所以不必擔心 沒 11 編譯器可用怎麼辦的問題

艹竟然不能匿名了


游標停在std::bind上,輕輕敲擊F12


補充遺漏的書名,汗…

去看一下。C++設計新思維,第一第二章就可以帶你解除這個迷惑


推薦閱讀:

如何正確理解boost::any的設計?
CUDA中可以用什麼來替代Vector類?
C++基本的知識都有了,但是很少C++解決問題,怎麼提高自己的實踐能力?
此處的C++斐波那契數列是如何實現的?
muduo::StringPiece?

TAG:C | BoostC庫 |