標準庫函數bind()和function()定義於頭文件中(該頭文件還包括許多其餘函數對象),用於處理函數及函數參數。bind()接受一個函數(或者函數對象,或者任何你能夠經過」(…)」符號調用的事物),生成一個其有某一個或多個函數參數被「綁定」或從新組織的函數對象。(譯註:顧名思義,bind()函數的意義就像它的函數名同樣,是用來綁定函數調用的某些參數的。)例如:函數
int f(int, char, double); // 綁定f()函數調用的第二個和第三個參數, // 返回一個新的函數對象爲ff,它只帶有一個int類型的參數 auto ff = bind(f, _1, ‘c’, 1.2); int x = ff(7); // f(7, ‘c’, 1.2);
參數的綁定一般稱爲」Currying」(譯註:Currying—「烹製咖喱燒菜」,此處意指對函數或函數對象進行加工修飾操做), 「_1″是一個佔位符對象,用於表示當函數f經過函數ff進行調用時,函數ff的第一個參數在函數f的參數列表中的位置。第一個參數稱爲」_1″, 第二個參數爲」_2″,依此類推。例如:this
int f(int, char, double); auto frev = bind(f, _3, _2, _1); // 翻轉參數順序 int x = frev(1.2, ‘c’, 7); // f(7, ‘c’, 1.2);
此處,auto關鍵字節約了咱們去推斷bind返回的結果類型的工做。指針
咱們沒法使用bind()綁定一個重載函數的參數,咱們必須顯式地指出須要綁定的重載函數的版本:code
int g(int); double g(double); auto g1 = bind(g, _1); // 錯誤:調用哪個g() ? // 正確,可是至關醜陋 auto g2 = bind( (double(*)(double))g, _1);
bind()有兩種版本:一個如上所述,另外一個則是「歷史遺留」的版本:你能夠顯式地描述返回類型。例如:對象
auto f2 = bind<int> (f, 7, ‘c’, _1); // 顯式返回類型 int x = f2(1.2); // f(7, ‘c’, 1.2);
第二種形式的存在是必要的,而且由於第一個版本((?) 「and for a user simplest 「,此處請參考原文))沒法在C++98中實現。因此第二個版本已經被普遍使用。回調函數
function是一個擁有任何能夠以」(…)」符號進行調用的值的類型。特別地,bind的返回結果能夠賦值給function類型。function十分易於使用。(譯註:更直觀地,能夠把function當作是一種表示函數的數據類型,就像函數對象同樣。只不過普通的數據類型表示的是數據,function表示的是函數這個抽象概念。)例如:io
// 構造一個函數對象, // 它能表示的是一個返回值爲float, // 兩個參數爲int,int的函數 function<float (int x, int y)> f; // 構造一個可使用"()"進行調用的函數對象類型 struct int_div { float operator() (int x, int y) const { return ((float)x)/y; }; }; f = int_div(); // 賦值 cout<< f(5,3) <<endl; // 經過函數對象進行調用 std::accumulate(b, e, 1, f); // 完美傳遞
成員函數可被看作是帶有額外參數的自由函數:function
struct X { int foo(int); }; // 所謂的額外參數, // 就是成員函數默認的第一個參數, // 也就是指向調用成員函數的對象的this指針 function<int (X*, int)> f; f = &X::foo; // 指向成員函數 X x; int v = f(&x, 5); // 在對象x上用參數5調用X::foo() function<int (int)> ff = std::bind(f, &x, _1); // f的第一個參數是&x v = ff(5); // 調用x.foo(5)
function對於回調函數、將操做做爲參數傳遞等十分有用。它能夠看作是C++98標準庫中函數對象mem_fun_t, pointer_to_unary_function等的替代品。一樣的,bind()也能夠被看作是bind1st()和bind2nd()的替代品,固然比他們更強大更靈活。class