1. 我们可以传递任何种callable object给算法,一个object或者expression 称为callable 是因为我们可以应用call operator。
我们说e是一个callable expression,那么我们可以写这样的代码:
<span style="font-size:18px;"><span style="white-space:pre"> </span>e(arg);</span>
arg是用逗号隔开的argument list。
2. callable:function,function pointer,重载了function call operator的class,以及lambda 表达式。
3. lambda表达式可以被认为是一种unnamed inline function。
4. lambda表达式的形式为:
<span style="font-size:18px;"><span style="white-space:pre"> </span>[capture list](parameter list)->return type{function body}</span>
5. lambda没有default argument,因此call a lambda 总是传递和parameter数量相同的argument。
6. lambda能够使用local variables只有当它specified它将要使用的variables才行。lambda通过将这些variables包括在他的capture list来specified这些variables。
7. 当我们定义一个lambda,编译器生成一个新的未命名的class type corresponds to that lambda。当我们传递一个lambda给一个function的时候,我们同时define一个new type以及一个这个type的object。
8. 当我们capture by value的时候,要确保variables能够被copy。同时,value of a capture variable 被copied当lambda被创造的时候,而不是被called的时候。
9. 当我们capture by reference的时候,要确保referenced的object当lambda执行的时候还存在。
10. 当我们implicit capture variables的时候,我们使用[&],[=]来告诉编译器我们到底是capture by reference还是capture by value。同时,当我们同时使用implicit capture 和explicit capture的时候,我们必须使capture list 的第一个是&或者=,同时explicit capture要和implicit capture的类型相反。
11. by default,lambda不会改变那些capture by value 的variable 的值,当我们想要改变的时候,我们这样:
<span style="font-size:18px;"><span style="white-space:pre"> </span>auto f=[v]mutable{return v++;}</span>
12. Bydefault,如果一个lambda的function body 包括除了return之外的其他语句,lambda都被认为return void。
如:
<span style="font-size:18px;"><span style="white-space:pre"> </span>transform(vi.begin(),vi.end(),vi.begin(),[](int i){if(i<0) return –I; else return I;}</span>
这导致error,因为lambda return a void type 但是我们返回了一个值。
当我们想要定义一个返回值的时候,我们可以这样做:
<span style="font-size:18px;"><span style="white-space:pre"> </span>transform(vi.begin(),vi.end(),vi.begin(),[](int i)->int
{ if(i<0) return –I; else return I;}</span>
13. 我们可以很容易将capture list 为空的lambda改为一个函数传递给算法,但是对于那些capture local variables 的lambda,则没有这么简单,因为算法通常用 unary predicate或者binary predicate。
14. 解决上面的问题,当我们需要将local variable传递到函数中,又希望可以将此函数传递给算法,我们可以使用bind function,如下:
<span style="font-size:18px;"><span style="white-space:pre"> </span>for_each(word.begin(),word.end(),
bind(print,ref(os),_1,’‘);</span>
在这里,newCallable就是一个callable object,arg_list是逗号隔开的argument list,correspond to parameter of callable。
在arg_list里会有一些_n的项,这些argument是placeholder,代表了newCallable中的parameter,_1代表newCallable的第一个parameter,_2代表第二个。
代码例子:
<span style="font-size:18px;"><span style="white-space:pre"> </span>auto wc=find_if(word.begin(),word.end(), bind(check_size,_1,sz));</span>
注:bind定义在functional头文件里。
15. _n定义在名叫placeholder的namespace里,placeholder又定义在std的namespace里,
<span style="font-size:18px;"><span style="white-space:pre"> </span>using::std::placeholder::_1;</span>
我们也可以这样简化
<span style="font-size:18px;"> <span style="white-space:pre"> </span>using namespace std::placeholder</span>
16. bind函数可以帮助我们对参数重排序。
<span style="font-size:18px;"><span style="white-space:pre"> </span>sort(word.begin(),word.end(),bind(isShorter,_2,_1);</span>
改变了参数顺序后,实际上使得排序方向正好相反。
17. 有时候,我们需要bind函数去binding reference parameter,通常那些不是placeholder的argument都是被copy到bind函数return的callable object里的。如果要binding reference parameter,可以这样做。
<span style="font-size:18px;"><span style="white-space:pre"> </span>for_each(word.begin(),word.end(),
bind(print,ref(os),_1,’‘);</span>
ref()函数返回一个包括了给定的reference的object,而且这个object是copyable的。我们还可以用cref()函数生成一个包括了reference to const的类。