我正設計一個布局類,對于托管的對象自動計算更新后的布局位置后調用用戶的回調函數(shù).bind用得非常high,然后最后卻編譯不過.
抽象出來就是如下代碼:
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
class test1
{
public:
template<typename S>
double handle(S s)
{
s(1);
std::cout<<"test1\n";
return 1;
}
template<typename F>
void handle1(F f) {
boost::bind(&test1::handle<F>,this,f)();//這里
}
};
class test2
{
public:
double handle(int i)
{
std::cout<<"test2\n";
return i;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
test2 t2;
test1 t1;
t1.handle1(boost::bind(&test2::handle,t2,_1));
return 0;
}
原來,bind為了支持
boost::bind( std::logical_and<bool>(), boost::bind(std::greater<int>(),_1,5), boost::bind(std::less_equal<int>(),_1,10));
這類操作,內部自動對bind_t(即bind的返回類型)調用取得結果來作參數(shù).代價就是不能把bind_t作為參數(shù)了.解決方法是,boost::ref包起來
boost::bind(&test1::handle<F>,this,boost::ref(f))();
boost user mail list有人建議
boost::bind(&test1::handle<boost::_bi::protected_bind_t<F>
>,this, protect(f))();
不過我認為用戶還是別去接觸boost::_bi空間來的好
另一件事是:bind返回的對象支持多于它本該支持的參數(shù).同樣上面的例子,改為
boost::bind(&test1::handle<F>,this,boost::ref(f))(1,2,3,4,5);
照樣編譯通過.帶來的好處就是像boost::asio這樣的庫接受的回調可以很靈活,你要不要boost::system::error_code,bytes_transferred都沒問題.asio::io_service總是壓入所有必須的參數(shù)來進行回調,而被bind后的回調對象會只抽取自己必須的參數(shù).