分享

使用lambda,远离bind

 quasiceo 2013-03-12
老实说,我不知道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.
posted on 2013-03-10 09:11 FireEmissary 阅读(1112) 评论(3)  编辑 收藏 引用

评论

# re: 使用lambda,远离bind 2013-03-11 00:57 YzL
auto是C++11才有的东西,而bind()已经存在并在旧的C++标准上实现了很久了,比如boost::bind(),并不是只有auto才能保存/推导bind()对象,模版也可以,看下面的代码:
template<typename CallType>
void Func(CallType call)
{
call();
}
这种情况bind()能生成/适配出实际上具有N个参数的call(),lambda则永远只能没参数,虽然lambda可以访问外部变量来模拟多参数,但是当Func()需要多次在不同的作用域调用、或者call()本身是第三方库时,bind()就要方便得多  回复  更多评论
 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多