boost.png (6897 bytes)

bind.hpp

 

Contents

目的

和函數及函數指針一起使用 bind

和函數對像一起使用 bind

和成員指針一起使用 bind

為函數組合使用嵌套的 binds

重載操作符

示例

和標準算法一起使用 bind

和 Boost.Function 一起使用 bind

局限性

常見問題

這個為什麼不能編譯?

這個為什麼能編譯?它應該不能。

bind(f, ...) 和 bind<R>(f, ...) 有什麼不同?

bind 可以和 Windows API 函數一起工作嗎?

bind 可以和 COM 方法一起工作嗎?

bind 可以和 Mac 工具箱涵數一起工作嗎?

bind 可以和 extern "C" 函數一起工作嗎?

bind 為什麼不能自動識別非標準函數?

故障診斷

錯誤的參數數量

函數對像不能被指定的參數調用

訪問一個不存在的參數

bind(f, ...) 的不恰當使用

bind<R>(f, ...) 的不恰當使用

綁定一個非標準函數

綁定一個被重載的函數

識別標識中的 const

MSVC 特有:using boost::bind;

MSVC 特有:類模板遮蓋函數模板

MSVC 特有:將識別標識中的 ... 看作類型

接口

概要

共通需求

共通定義

bind

補充重載

實現

文件

相關內容

參數數量

"__stdcall", "__cdecl", "__fastcall", 和 "pascal" 支持

visit_each 支持

感謝

Purpose(目的)

boost::bind 是標準函數 std::bind1ststd::bind2nd 的泛化。它支持任意的函數對象,函數,函數指針,和成員函數指針,它還能將任何參數綁定為一個特定的值,或者將輸入的參數發送到任意的位置。bind 對函數對像沒有任何要求,特別是,它不需要 result_typefirst_argument_typesecond_argument_type 這樣的標準 typedefs。

Using bind with functions and function pointers(和函數及函數指針一起使用 bind)

給定這些定義:

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, _1, 5)(x) 等價於 f(x, 5),這裡,_1 是一個佔位符參數,它的含義是「用第一個輸入參數取代」。

作為對照,這是用標準庫原始形式表達的同樣操作:

std::bind2nd(std::ptr_fun(f), 5)(x);

bind 同樣覆蓋了 std::bind1st 的功能:

std::bind1st(std::ptr_fun(f), 5)(x);   // f(5, x)
bind(f, 5, _1)(x);                     // f(5, x)

bind 能夠處理帶有兩個以上參數的函數,而且它的參數取代機制更為直觀:

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) 生成的函數對像不包含對第一個參數以外的任何參數的引用,但是它仍然能使用一個以上的參數。所有多餘的參數被悄悄地忽略,就像在第三個示例中,第一和第二個參數被忽略。

bind 持有的參數被返回的函數對像拷貝並內部持有。例如,在下面的代碼中:

int i = 5;

bind(f, i, _1);

一個 i 的值的拷貝被存儲於函數對像中。boost::refboost::cref 可用於讓函數對像存儲一個引用而不是拷貝:

int i = 5;

bind(f, ref(i), _1);

bind(f, cref(42), _1);

Using bind with function objects(和函數對像一起使用 bind)

bind 並不限於函數,它可以接受任何函數對象。通常情況下,生成的函數對象的 operator() 的返回類型必須顯式指定(沒有 typeof 操作符,返回類型無法推導):

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;

bind<int>(f, _1, _1)(x);		// f(x, x), i.e. zero

有些編譯器遇到 bind<R>(f, ...) 語法會發生問題。出於可移植性的原因,一種和上面的意思相同的可選的表達方式也被支持:

boost::bind(boost::type<int>(), f, _1, _1)(x);

但是要注意,這種可選語法只是作為一個 workaround 提供。它不是接口的一部分。

當函數對像暴露了一個名為 result_type 的內嵌類型時,顯式返回類型可以被省略:

int x = 8;

bind(std::less<int>(), _1, 9)(x);	// x < 9

【注意:這種省略返回類型的能力並非在所有的編譯器上都可用。】

缺省情況下,bind 為提供的函數對像做出一份拷貝。boost::refboost::cref 可用於讓它存儲這個函數對象的引用,而非拷貝。當函數對象是不可拷貝的,拷貝代價高昂,或者包含狀態時是很有用的,當然,在這種情況下,要求程序員確保這個函數對像在使用期間不能被銷毀。

struct F2
{
    int s;

    typedef void result_type;
    void operator()( int x ) { s += x; }
};

F2 f2 = { 0 };
int a[] = { 1, 2, 3 };

std::for_each( a, a+3, bind( ref(f2), _1 ) );

assert( f2.s == 6 );

Using bind with pointers to members(和成員指針一起使用 bind)

成員函數的指針和數據成員的指針不是函數對象,因為它們不支持 operator()。為了方便起見,bind 接受成員指針作為它的第一個參數,而它的行為就像使用 boost::mem_fn 將成員指針轉換成一個函數對像一樣。換句話說,當 RX::f 的返回類型(作為成員函數)或成員本身的類型(作為數據成員)時,表達式

bind(&X::f, args)

bind<R>(mem_fn(&X::f), args)

等價。

【注意:mem_fn 創建的函數對象可以接受一個對象的指針,引用或智能指針作為它的第一個參數,更多的信息,參見 mem_fn 文檔。】

示例:

struct X
{
    bool f(int a);
};

X x;

shared_ptr<X> p(new X);

int i = 5;

bind(&X::f, ref(x), _1)(i);		// x.f(i)
bind(&X::f, &x, _1)(i);			//(&x)->f(i)
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() 之後,這個引用依然保持有效。

Using nested binds for function composition(為函數組合使用嵌套的 binds)

傳給 bind 的某些參數可以嵌套 bind 表達式自身:

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))

bind 的這個特性可被用來執行函數組合。參見示例 bind_as_compose.cpp,示範如何用 bind 達到與 Boost.Compose 類似的功能。

注意第一個參數——被綁定函數對像——是不被求值的,即使它是一個由 bind 生成的函數對像或一個佔位符參數,所以下面的示例不會如你所願地工作:

typedef void (*pf)(int);

std::vector<pf> v;

std::for_each(v.begin(), v.end(), bind(_1, 5));

你所要的效果,可以通過將一個輔助函數對像 apply 用作它的第一個參數而獲得,作為一個函數對象,它可以支撐它的參數列表。為了方便起見,在 boost/bind/apply.hpp 頭文件中提供了一個 apply 的實現。下面是一個前面的示例的修改版本:

typedef void (*pf)(int);

std::vector<pf> v;

std::for_each(v.begin(), v.end(), bind(apply<void>(), _1, 5));

儘管在缺省情況下,第一個參數是不被求值的,而所有其它參數被求值。但有時候不需要對第一個參數之後的其它參數求值,甚至當它們是內嵌 bind 子表達式的時候也不需要。這可以由另一個函數對像 protect 來幫助做到,它將類型掩飾起來,讓 bind 無法對它進行識別和求值。在被調用的時候,protect 只是簡單地不加更改地將參數列表轉送到其它函數對像中。

頭文件 boost/bind/protect.hpp 包含一個 protect 的實現。要在求值中保護一個 bind 函數對象,使用 protect(bind(f, ...))

Overloaded operators (new in Boost 1.33)(重載的操作符(Boost 1.33 新增))

為了方便起見,由 bind 生成的函數對像重載了 logical not(邏輯非)操作符 ! 和關係操作符 ==, !=, <, <=, >, >=, &&, ||

如果 logical_not 是一個持有一個參數 x 並返回 !x 的函數對象,則 !bind(f, ...) 等價於 bind( logical_not(), bind(f, ...) )

如果 op 是一個關係或邏輯操作符,並且 relation 是一個持有兩個參數 ab 並返回 a op b 的函數對象,則 bind(f, ...) op x 等價於 bind( relation(), bind(f, ...), x )

這實際上意味著你可以方便地對 bind 的結果求非:

std::remove_if( first, last, !bind( &X::visible, _1 ) ); // remove invisible objects

以及方便地將 bind 的結果和一個值進行比較:

std::find_if( first, last, bind( &X::name, _1 ) == "Peter" );

std::find_if( first, last, bind( &X::name, _1 ) == "Peter" || bind( &X::name, _1 ) == "Paul" );

和一個佔位符進行比較:

bind( &X::name, _1 ) == _2

或者和另一個 bind 表達式進行比較:

std::sort( first, last, bind( &X::name, _1 ) < bind( &X::name, _2 ) ); // sort by name

Examples(示例)

Using bind with standard algorithms(和標準算法一起使用 bind)

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(), boost::bind(&animation::advance, _1, ms));
    erase_if(anims, boost::mem_fn(&animation::inactive));
}

void render(image & target)
{
    std::for_each(anims.begin(), anims.end(), boost::bind(&animation::render, _1, boost::ref(target)));
}

Using bind with Boost.Function(和 Boost.Function 一起使用 bind)

class button
{
public:

    boost::function<void()> onClick;
};

class player
{
public:

    void play();
    void stop();
};

button playButton, stopButton;
player thePlayer;

void connect()
{
    playButton.onClick = boost::bind(&player::play, &thePlayer);
    stopButton.onClick = boost::bind(&player::stop, &thePlayer);
}

Limitations(局限性)

作為一個通用規則,由 bind 生成的函數對像以引用方式持有它們的參數,因此,不能接受非 const 臨時對像或字面常量。這是 C++ 語言的當前(2003)版本與生俱來的局限,稱為 the forwarding problem。(它將在下一版標準(通常稱為 C++0x)中被修正。)

這個庫以下面這種形式的識別標識

template<class T> void f(T & t);

接受任意類型的參數並將它們不加改變地傳遞。注意,這不能用於非 const 右值。

在支持函數模板部分排序的編譯器上,一個可能的解決方案是增加一個重載:

template<class T> void f(T & t);
template<class T> void f(T const & t);

很不幸,對於 9 個參數,這樣需要提供 512 個重載,這是不切實際的。這個庫選擇了一個小的子集:對於不大於兩個參數的情況,完整地提供了常量重載,對於三個及更多參數,它為所有參數都以常引用方式持有的情況提供了單一的補充重載。這覆蓋了使用情況的一個合理的部分。

Frequently Asked Questions(常見問題)

Why doesn't this compile?(這個為什麼不能編譯?)

參見專門的 Troubleshooting(故障診斷)部分

Why does this compile? It should not.(這個為什麼能編譯?它應該不能。)

Probably because you used the general bind<R>(f, ...) syntax,

也許是因為你使用了通用的 bind<R>(f, ...) 語法,從而指示 bind 不需要「檢查」 f 以查明參數數量和返回類型的錯誤。

What is the difference between bind(f, ...) and bind<R>(f, ...)?(bind(f, ...) 和 bind<R>(f, ...) 有什麼不同?)

第一個形式指示 bind 去檢查 f 的類型以確定它的 arity(參數數量)和返回類型。參數數量錯誤將在「綁定時間」查明。當然,這樣的語法對 f 有一定的要求。它必須是一個函數,函數指針,成員函數指針,或定義了一個內嵌的名為 result_type 的類型的函數對象,簡而言之,它必須是某種 bind 可以識別的東西。

第二個形式指示 bind 不要試圖識別 f 的類型。它通常和那些沒有或不能暴露 result_type 的函數對像一起使用,但是它也能和非標準函數一起使用。例如,當前實現不能自動識別像 printf 這樣的可變參數函數,所以你必須用 bind<int>(printf, ...)。注意,有一種可選的 bind(type<R>(), f, ...) 語法因為可移植性的原因也被支持。

另一個需要考慮的重要因素是:當 f 是一個函數對像時,不支持模板偏特化或函數模板部分排序的編譯器不能處理第一種形式,而且,大部分情況下,當 f 是一個函數(指針)或成員函數指針時,不能處理第二種形式。

Does bind work with Windows API functions?(bind 可以和 Windows API 函數一起工作嗎?)

可以,只要你 #define BOOST_BIND_ENABLE_STDCALL。另一個可選方法是將這個函數看成一個一般函數對像並使用 bind<R>(f, ...) 語法。

Does bind work with COM methods?(bind 可以和 COM 方法一起工作嗎?)

可以,只要你 #define BOOST_MEM_FN_ENABLE_STDCALL

Does bind work with Mac toolbox functions?

可以,只要你 #define BOOST_BIND_ENABLE_PASCAL。另一個可選方法是將這個函數看成一個一般函數對像並使用 bind<R>(f, ...) 語法。

Does bind work with extern "C" functions?(bind 可以和 extern "C" 函數一起工作嗎?)

有時可以。在一些平台上,extern "C" 函數指針等價於「一般的」函數指針,所以它們能很好地工作。另一些平台將它們看做不同的類型。期待一個平台相關的 bind 實現顯然可以解決問題,但這個實現不行。照例,workaround 將這個函數看成一個一般函數對像並使用 bind<R>(f, ...) 語法。

Why doesn't bind automatically recognize nonstandard functions?(bind 為什麼不能自動識別非標準函數?)

一般而言,不可移植擴展在默認狀態下應該關閉,以預防被廠商鎖定。如果適當的宏被自動定義,你可能無意中使用了它而並不確定你的代碼也許不能再移植。另外,有些編譯器有選項讓 __stdcall (__fastcall) 成為它們缺省的調用約定,在這種情況下,就不再需要個別的支持。

Troubleshooting(故障診斷)

Incorrect number of arguments(錯誤的參數數量)

在表達式 bind(f, a1, a2, ..., aN) 中,函數對像 f 必須能夠持有正好 N 個參數。這個錯誤通常在「綁定時間」被查出。換句話說,這個編譯錯誤會被報告在 bind() 被調用的那一行:

int f(int, int);

int main()
{
    boost::bind(f, 1);    // error, f takes two arguments
    boost::bind(f, 1, 2); // OK
}

這個錯誤的一個常見變化是忘記成員函數有一個隱含的 "this" 參數:

struct X
{
    int f(int);
}

int main()
{
    boost::bind(&X::f, 1);     // error, X::f takes two arguments
    boost::bind(&X::f, _1, 1); // OK
}

The function object cannot be called with the specified arguments(函數對像不能被指定的參數調用)

和通常的函數調用一樣,被綁定的函數對像必須和參數列表一致。這種不一致通常在「調用時間」被編譯器檢測出來,而結果通常是在 bind.hpp 中類似下面這樣的一行中的錯誤:

    return f(a[a1_], a[a2_]);

這種錯誤的一個示例如下:

int f(int);

int main()
{
    boost::bind(f, "incompatible");      // OK so far, no call
    boost::bind(f, "incompatible")();    // error, "incompatible" is not an int
    boost::bind(f, _1);                  // OK
    boost::bind(f, _1)("incompatible");  // error, "incompatible" is not an int
}

Accessing an argument that does not exist(訪問一個不存在的參數)

佔位符 _N 選擇在「調用時間」被傳遞的參數列表的第 N 個參數。很自然,這是一個試圖訪問超出這個列表的末尾的錯誤:

int f(int);

int main()
{
    boost::bind(f, _1);                  // OK
    boost::bind(f, _1)();                // error, there is no argument number 1
}

這個錯誤通常被報告在 bind.hpp 中,類似下面這樣的一行中:

    return f(a[a1_]);

一個常見的這類錯誤是在模仿 std::bind1st(f, a) 時,鍵入 bind(f, a, _2),而不是正確的 bind(f, a, _1)

Inappropriate use of bind(f, ...)(bind(f, ...) 的不恰當使用)

bind(f, a1, a2, ..., aN) 形式引起對 f 的類型的自動檢測。它不能和任意的函數對像一起工作,f 必須是一個函數或成員函數指針。

定義了 result_type 的函數對像使用這種形式也是允許的,但是只有在編譯器支持偏特化和部分排序的時候才可以。特別是,MSVC 直到版本 7.0 還不支持函數對象的這種語法。

Inappropriate use of bind<R>(f, ...)(bind<R>(f, ...) 的不恰當使用)

bind<R>(f, a1, a2, ..., aN) 形式支持任意函數對象。

將這種形式用於函數或成員函數指針也是允許的(但不推薦),但是只有在編譯器支持部分排序時才行。特別是,MSVC 直到版本 7.0 還不完全支持函數和成員函數指針的這種語法。

Binding a nonstandard function(綁定一個非標準函數)

缺省情況下,bind(f, a1, a2, ..., aN) 形式識別「一般的」C++ 函數和函數指針。使用不同的調用約定的函數或像 std::printf 這樣的可變參數函數不能工作。通用的 bind<R>(f, a1, a2, ..., aN) 形式和非標準函數一起工作。

在一些平台上,extern "C" 函數,比如 std::strcmp 不能被短形式的 bind 識別。

參見 "__stdcall" 和 "pascal" 支持

Binding an overloaded function(綁定一個被重載的函數)

綁定一個被重載的函數的企圖通常對導致一個錯誤,因為無法表示到底要綁定哪一個重載版本。對於帶有 const 和非 const 兩個重載的成員函數來說,這是一個很常見的問題,就像這個簡化的示例:

struct X
{
    int& get();
    int const& get() const;
};

int main()
{
    boost::bind( &X::get, _1 );
}

這裡的二義性可以通過將(成員)函數指針強制轉換到想要的類型來解決:

int main()
{
    boost::bind( static_cast< int const& (X::*) () const >( &X::get ), _1 );
}

另一個或許更可讀的辦法是引入一個臨時變量:

int main()
{
    int const& (X::*get) () const = &X::get;
    boost::bind( get, _1 );
}

const in signatures(識別標識中的 const

有些編譯器,包括 MSVC 6.0 和 Borland C++ 5.5.1,處理函數識別標識中的頂層 const 存在問題:

int f(int const);

int main()
{
    boost::bind(f, 1);     // error
}

workaround:從參數中移除 const 修飾符。

MSVC specific: using boost::bind;(MSVC 特有:using boost::bind;)

在 MSVC(直到版本 7.0)上,當 boost::bind 是由一個 using 聲明:

using boost::bind;

帶入當前作用域的時候,語法 bind<R>(f, ...) 不能工作。workaround:使用被限定的名字,boost::bind,或者用 using 指令代替:

using namespace boost;

MSVC specific: class templates shadow function templates(MSVC 特有:類模板遮蓋函數模板)

在 MSVC(直到版本 7.0)上,一個內嵌的名為 bind 的類模板會遮蓋函數模板 boost::bind,破壞了 bind<R>(f, ...) 語法。很不幸,某些庫包含內嵌的名為 bind 的類模板(諷刺的是,這些代碼常常是某個 MSVC 特有的 workaround)。

workaround 是使用可選的 bind(type<R>(), f, ...) 語法。

MSVC specific: ... in signatures treated as type(MSVC 特有:將識別標識中的 ... 看作類型)

在 MSVC(直到版本 7.0)將可變參數函數(比如 std::printf)中的省略號看作一個類型。因此,它會接受(在當前實現中是錯誤的)形式:

    bind(printf, "%s\n", _1);

並會拒絕正確版本:

    bind<int>(printf, "%s\n", _1);

Interface(接口)

Synopsis(概要)

namespace boost
{

// no arguments

template<class R, class F> unspecified-1 bind(F f);

template<class F> unspecified-1-1 bind(F f);

template<class R> unspecified-2 bind(R (*f) ());

// one argument

template<class R, class F, class A1> unspecified-3 bind(F f, A1 a1);

template<class F, class A1> unspecified-3-1 bind(F f, A1 a1);

template<class R, class B1, class A1> unspecified-4 bind(R (*f) (B1), A1 a1);

template<class R, class T, class A1> unspecified-5 bind(R (T::*f) (), A1 a1);

template<class R, class T, class A1> unspecified-6 bind(R (T::*f) () const, A1 a1);

template<class R, class T, class A1> unspecified-6-1 bind(R T::*f, A1 a1);

// two arguments

template<class R, class F, class A1, class A2> unspecified-7 bind(F f, A1 a1, A2 a2);

template<class F, class A1, class A2> unspecified-7-1 bind(F f, A1 a1, A2 a2);

template<class R, class B1, class B2, class A1, class A2> unspecified-8 bind(R (*f) (B1, B2), A1 a1, A2 a2);

template<class R, class T, class B1, class A1, class A2> unspecified-9 bind(R (T::*f) (B1), A1 a1, A2 a2);

template<class R, class T, class B1, class A1, class A2> unspecified-10 bind(R (T::*f) (B1) const, A1 a1, A2 a2);

// implementation defined number of additional overloads for more arguments

}

namespace
{

unspecified-placeholder-type-1 _1;

unspecified-placeholder-type-2 _2;

unspecified-placeholder-type-3 _3;

// implementation defined number of additional placeholder definitions

}

Common requirements(共通需求)

所有由 bind 返回的 unspecified-N 類型都是 CopyConstructible(可拷貝構造)的。unspecified-N::result_type 被定義為 unspecified-N::operator() 的返回類型。

所有 unspecified-placeholder-N 都是 CopyConstructible(可拷貝構造)的。它們的拷貝構造函數不會拋出異常。

Common definitions(共通定義)

當 m 是一個非負整數時,函數 μ(x, v1, v2, ..., vm) 被定義為:

bind

template<class R, class F> unspecified-1 bind(F f)

返回:一個使得表達式 λ(v1, v2, ..., vm) 等價於 f() 的函數對像 λ,隱式轉換為 R

拋出:不拋出異常,除非 F 的拷貝構造函數拋出異常。

template<class F> unspecified-1-1 bind(F f)

效果:等價於 bind<typename F::result_type, F>(f);

注意:作為一種擴展,實現允許通過其它手段推斷 f 的返回類型,而不依賴於 result_type 成員。

template<class R> unspecified-2 bind(R (*f) ())

返回:一個使得表達式 λ(v1, v2, ..., vm) 等價於 f() 的函數對像 λ

拋出:不拋出異常。

template<class R, class F, class A1> unspecified-3 bind(F f, A1 a1)

返回:一個使得表達式 λ(v1, v2, ..., vm) 等價於 f(μ(a1, v1, v2, ..., vm)) 的函數對像 λ,隱式轉換為 R

拋出:不拋出異常,除非 FA1 的拷貝構造函數拋出異常。

template<class F, class A1> unspecified-3-1 bind(F f, A1 a1)

效果:等價於 bind<typename F::result_type, F, A1>(f, a1);

注意:作為一種擴展,實現允許通過其它手段推斷 f 的返回類型,而不依賴於 result_type 成員。

template<class R, class B1, class A1> unspecified-4 bind(R (*f) (B1), A1 a1)

返回:一個使得表達式 λ(v1, v2, ..., vm) 等價於 f(μ(a1, v1, v2, ..., vm)) 的函數對像 λ

拋出:不拋出異常,除非 A1 的拷貝構造函數拋出異常。

template<class R, class T, class A1> unspecified-5 bind(R (T::*f) (), A1 a1)

效果:等價於 bind<R>(boost::mem_fn(f), a1);

template<class R, class T, class A1> unspecified-6 bind(R (T::*f) () const, A1 a1)

效果:等價於 bind<R>(boost::mem_fn(f), a1);

template<class R, class T, class A1> unspecified-6-1 bind(R T::*f, A1 a1)

效果:等價於 bind<R>(boost::mem_fn(f), a1);

template<class R, class F, class A1, class A2> unspecified-7 bind(F f, A1 a1, A2 a2)

返回:一個使得表達式 λ(v1, v2, ..., vm) 等價於 f(μ(a1, v1, v2, ..., vm), μ(a2, v1, v2, ..., vm)) 的函數對像 λ,隱式轉換為 R

拋出:不拋出異常,除非 FA1A2 的拷貝構造函數拋出異常。

template<class F, class A1, class A2> unspecified-7-1 bind(F f, A1 a1, A2 a2)

效果:等價於 bind<typename F::result_type, F, A1, A2>(f, a1, a2);

注意:作為一種擴展,實現允許通過其它手段推斷 f 的返回類型,而不依賴於 result_type 成員。

template<class R, class B1, class B2, class A1, class A2> unspecified-8 bind(R (*f) (B1, B2), A1 a1, A2 a2)

返回:一個使得表達式 λ(v1, v2, ..., vm) 等價於 f(μ(a1, v1, v2, ..., vm), μ(a2, v1, v2, ..., vm)) 的函數對像 λ

拋出:不拋出異常,除非 A1A2 的拷貝構造函數拋出異常。

template<class R, class T, class B1, class A1, class A2> unspecified-9 bind(R (T::*f) (B1), A1 a1, A2 a2)

效果:等價於 bind<R>(boost::mem_fn(f), a1, a2);

template<class R, class T, class B1, class A1, class A2> unspecified-10 bind(R (T::*f) (B1) const, A1 a1, A2 a2)

效果:等價於 bind<R>(boost::mem_fn(f), a1, a2);

Additional overloads(補充重載)

實現允許提供補充的 bind 重載以支持更多的參數或不同的函數指針變種。

Implementation(實現)

Files(文件)

Dependencies(相關內容)

Number of Arguments(參數數量)

這個實現支持最多 9 個參數的函數對象。這是一個實現細節,不是設計的固有限制。

"__stdcall", "__cdecl", "__fastcall", and "pascal" Support("__stdcall", "__cdecl", "__fastcall", 和 "pascal" 支持)

有些平台允許通過調用約定(函數被調用時的規則:參數如何傳遞,返回值如何處理,誰來清理棧(如果有的話))來區分(成員)函數的若干類型。

例如,Windows API 函數和 COM 接口成員函數使用一種名為 __stdcall 的調用約定。Borland VCL 組件使用 __fastcall。Mac 工具箱涵數使用一種 pascal 調用約定。

為了和 __stdcall 函數一起使用 bind,在包含 <boost/bind.hpp> 之前 #defineBOOST_BIND_ENABLE_STDCALL

為了和 __stdcall 成員函數一起使用 bind,在包含 <boost/bind.hpp> 之前 #defineBOOST_MEM_FN_ENABLE_STDCALL

為了和 __fastcall 函數一起使用 bind,在包含 <boost/bind.hpp> 之前 #defineBOOST_BIND_ENABLE_FASTCALL

為了和 __fastcall 成員函數一起使用 bind,在包含 <boost/bind.hpp> 之前 #defineBOOST_MEM_FN_ENABLE_FASTCALL

為了和 pascal 函數一起使用 bind,在包含 <boost/bind.hpp> 之前 #defineBOOST_BIND_ENABLE_PASCAL

為了和 __cdecl 成員函數一起使用 bind,在包含 <boost/bind.hpp> 之前 #defineBOOST_MEM_FN_ENABLE_CDECL

最好在項目選項中定義這些宏,在命令行上使用 –D,或作為使用了 bind 的翻譯單元(.cpp 文件)的第一行。不遵守這個規則,當一個包含了 bind.hpp 的頭文件出現在這些宏被定義之前,可能會導致隱蔽的錯誤。

【注意:這是一個不可移植擴展。它不是接口的一部分。】

【注意:有些編譯器只對 __stdcall 關鍵字提供最小的支持。】

visit_each support(visit_each 支持)

bind 返回的函數對像支持到目前為止尚處於實驗性和未文檔化的 visit_each 枚舉接口。

示例參見 bind_visitor.cpp

Acknowledgements(感謝)

影響這個庫設計的早期成就:

Doug Gregor 建議了一種訪問者機制可以允許 bind 和 signal/slot 庫進行互操作。

John Maddock 修復了一個 MSVC 特有的在 bindtype traits 庫之間的衝突。

正式 review 期間,Ross Smith,Richard Crossley,Jens Maurer,Ed Brey 和其他人提出大量改進建議。review 主管者是 Darin Adler。

在和 Jaakko Jarvi 的討論中 bind 的精確語義更加優雅。

John Maddock 修復了一個 MSVC 特有的在 binditerator adaptors 庫之間的衝突。

Dave Abrahams 改良了 bindmem_fn 以支持在不完善編譯器上的空返回。

Mac Murrett 通過 BOOST_BIND_ENABLE_PASCAL 實現並貢獻了 "pascal" 支持。

可選的 bind(type<R>(), f, ...) 語法的靈感來自於和 Dave Abrahams 與 Joel de Guzman 的一次討論。




Copyright c 2001, 2002 by Peter Dimov and Multi Media Ltd. Copyright 2003-2008 Peter Dimov. Distributed under the Boost Software License, Version 1.0. See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.