老实说,我不知道C++11有了lambda,怎么还会要引入bind.
bind这玩意,嵌套两层就得出汗,嵌套三四层绝对要人提心吊胆验证n久.还有个自以为是的功能:如果绑定的参数是bind对象,它就自作聪明去调用.问题是,有时候你确实要个可调用对象而不是可调用对象的调用返回值,你要不就得用ref包裹bind,要不就得格外写个可调用对象使得
std::is_bind_expression<T>::value == true判断不成立.这格外写个可调用对象的简单方法是什么:就是用lambda.....
有人会说:bind能做的事lambda不能做,比如bind可以绑定一个可调用对象,这个可调用对象有多个可调用operator call或者template call.如下:
struct foo
{
typedef void result_type;
template < typename A, typename B >
void operator()(A a, B b)
{
std::cout << "operator()(A a, B b)"<<std::endl;
}
void operator()(int a,int b)
{
std::cout << "operator()(int a,int b)"<<std::endl;
}
int operator()(int a,char b)
{
std::cout << "operator()(int a,char b)"<<std::endl;
return 1;
}
};
int main()
{
using namespace std::placeholders;
auto f = std::bind(foo(), _1,_2);
f("test", 1.2f);
f(2,3);
std::cout<<"get:"<<f(2,'3');
return 0;
}
没错,lambda必须指定函数参数类型,表面上看也许没那么"可变".然而你要考虑实际应用场景.bind一个对象后怎么用它呢?一般使用场景是保存起来以备使用.而目前class 成员显然不是一个auto可以指定,它得是具体的类型,比如std::function<void(int ,float)>.如果把上面代码里的 f保存在一个std::function<void(int ,float)>类型里面,那么当后来调用它传入两个整型时会调用哪个函数?不是
operator()(int a,int b) 而是operator()(A a, B b)!所以除非你bind一个对象后立马在当前函数里使用(多此一举),否则bind的参数灵活性基本发挥不出来.
这就给出了两个易出错场景:
一个是传给bind的参数是可调用对象是,表现不一样(可调用对象是另一个bind时,会被调用,其它则当成普通对象)
另一个是对于bind一个类,类里面有多个可调用函数时,出现你以为调用
operator()(int a,int b) 而实际上是operator()(A a, B b).反之lambda的直观使得它更容易找出问题.
再加上bind多层嵌套使用带来的可读性问题(这其实也是易出错场景),我的看法是:学好lambda,远离bind.