我正设计一个布局类,对于托管的对象自动计算更新后的布局位置后调用用户的回调函数.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的返回类型)调用取得结果来作参数.代价就是不能把bind_t作为参数了.解决方法是,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返回的对象支持多于它本该支持的参数.同样上面的例子,改为
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总是压入所有必须的参数来进行回调,而被bind后的回调对象会只抽取自己必须的参数.