boost中有一個bind庫, 能夠說是一個最爲實用的tools了, 可是它與boost結合的有些緊密,並且其中的一些功能並非很經常使用,就算將它bcp出獨立的庫也是一個不小的負擔。若是在你的項目中不打算有boost庫的痕跡可是又想使用bind的強大功能,那就來看看它吧。
一個一個超小型的bind庫, 它實現了大部分boost::bind的功能, 只是將名字空間由boost 變換爲 bi 。若是使用了通常的使用中一般能夠將 html
boost::bind(my_fun(), _1,_2)(234, "hello world"); //形式替換爲 bi::bind(my_fun(), _1, _2)(234, "hello world");
int f(int a, int b) { return a + b; } int g(int a, int b, int c) { return a + b + c; }bind(f, 1, 2) 會產生一個函數對象,它將f(1, 2)這樣的函數調用包裝到了自身,一樣,bind(g, 1, 2, 3)() 的形式調用等價於 g(1, 2, 3)。
bind(f, _2, _1)(x, y); // f(y, x) bind(g, _1, 9, _1)(x); // g(x, 9, x) bind(g, _3, _3, _3)(x, y, z); // g(z, z, z) bind(g, _1, _1, _1)(x, y, z); // g(x, x, x)注意,最後一個示例中,由 bind(g, _1, _1, _1) 生成的函數對象不包含對第一個參數之外的任何參數的引用,可是它仍然能使用一個以上的參數。全部多餘的參數被悄悄地忽略,就像在第三個示例中,第一和第二個參數被忽略。
int i = 5; bind(f, i, _1);一個 i 的值的拷貝被存儲於bind生成的函數對象中。
int f(int, int); int main() { bi::bind(f, 1); // error, f函數f必須具有兩個參數 bi::bind(f, 1, 2); // OK }這個錯誤的一個常見變化是忘記成員函數有一個隱含的 "this" 參數:
struct X { int f(int); }; int main() { bi::bind(&X::f, 1); // error,函數f必須具有兩個參數 bi::bind(&X::f, _1, 1); // OK }和函數對象一塊兒使用 bind
struct F { int operator()(int a, int b) { return a - b; } bool operator()(long a, long b) { return a == b; } }; F f; int x = 104; bi::bind(bi::type<int>(), f, _1, _1)(x);bi::bind庫不支持 bind<int>(f, _1, _1)(x); 形式的調用, boost支持這種調用方式。
int x = 8; bind(std::less<int>(), _1, 9)(x); // x < 9bind(f, ...) 和 bind<R>(f, ...) 有什麼不一樣
struct X { bool f(int a); }; X x; Boost::shared_ptr<X> p(new X); //天然支持 boost::shared_ptr int i = 5; bind(&X::f, x, 1)(i); // ( _internal copy of x).f(i) bind(&X::f, p, 1)(i); // ( _internal copy of p)->f(i)最後兩個示例的有趣之處在於它們生成「自包含」的函數對象。bind(&X::f, x, _1) 存儲 x 的一個拷貝。bind(&X::f, p, _1) 存儲 p 的一個拷貝,並且由於 p 是一個 boost::shared_ptr,這個函數對象保存一個屬於它本身的 X 的實例的引用,並且當 p 離開它的做用域或者被 reset() 以後,這個引用依然保持有效。
struct X { int& get(); int const& get() const; }; int main() { bi::bind( &X::get, _1 ); }這裏的二義性能夠經過將(成員)函數指針強制轉換到想要的類型來解決:
int main() { bi::bind( static_cast< int const& (X::*) () const >( &X::get ), _1 ); }另外一個或許更可讀的辦法是引入一個臨時變量:
int main() { int const& (X::*get) () const = &X::get; bi::bind( get, _1 ); }爲函數組合使用嵌套的 binds
bind(f, bind(g, _1))(x); // f(g(x))當函數對象被調用的時候,若是沒有指定順序,內部 bind 表達式先於外部 bind 表達式被求值,在外部 bind 表達式被求值的時候,用內部表達式的求值結果取代它們的佔位符的位置。在上面的示例中,當用參數列表 (x) 調用那個函數對象的時候,bind(g, _1)(x) 首先被求值,生成 g(x),而後 bind(f, g(x))(x) 被求值,生成最終結果 f(g(x))。
typedef void (pf)(int); std::vector<pf> v; std::for_each(v.begin(), v.end(), bind(_1, 5));儘管在缺省狀況下,第一個參數是不被求值的,而全部其它參數被求值。但有時候不須要對第一個參數以後的其它參數求值,甚至當它們是內嵌 *bind 子表達式的時候也不須要。
示例
和標準算法一塊兒使用 bind c++
class image; class animation { public: void advance(int ms); bool inactive() const; void render(image & target) const; }; std::vector<animation> anims; template<class C, class P> void erase_if(C & c, P pred) { c.erase(std::remove_if(c.begin(), c.end(), pred), c.end()); } void update(int ms) { std::for_each(anims.begin(), anims.end(), ni::bind(&animation::advance, _1, ms)); erase_if(anims, bi::mem_fn(&animation::inactive)); } void render(image & target) { std::for_each(anims.begin(), anims.end(), bi::bind(&animation::render, _1, bi::ref(target))); }侷限性
bi-bind 同時提供了 callback功能, 它就像是一個簡化版本的 boost::function, 對一次調用行爲作了抽象。 算法
int fun1(int p2) { std::cout << "call fun1" << std::endl; return p2 * p2; } struct fun2 { fun2(int p1) { p_ = p1; } int operator()(int p2) const { return p2 * p_; } int p_; };//綁定通常函數 構造 callback
struct fun2 { fun2(int p1) { p_ = p1; } int operator()(int p2) const { return p2 * p_; } int p_; };
//假設fun2的拷貝複製的負擔很大 fun2 f(23); //使用bi::ref解除對f對像的值語義調用 bi::bind(bi::ref(f), 9)(2);我沒有寫bi::bind的使用文檔, 由於它 在這裏 http://www.boost.org/doc/libs/1_49_0/libs/bind/bind.html。 庫地址: http://code.google.com/p/bi-bind/