c++ bind

標準庫函數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

相關文章
相關標籤/搜索