predicate(谓词)
predicate是一个可以调用的表达式,其返回结果是一个能用作条件的值
- 一元predicate只接受单一参数,
- 二元prediacte接受两个参数
lambda表达式
背景
像find_if这样的函数其第三个参数接受一个一元predicate,即传递给find_if的任何函数都必须严格接受一个参数。
lambda
一个lambda表达式表示一个可以被调用的代码单元。我们可以将其理解为一个未命名的内联参数。
[capture list](parameter list) -> return type {function body}
- capture list是一个lambda所在函数中定义的局部变量的列表。
- 其余与普通函数意义一样。
- lambda参数列表中不能有默认参数。
- 可以忽略parameter和return type,但是必须永远包含capture和function body。
若忽略返回类型, lambda根据函数体中的代码推断返回类型。若有return语句,则根据return判断,否则返回类型为void。
int temp;
auto iter = find_if(para.begin(),para.end(), [temp] (const int b){return a >= temp});
//这样就等同于find_if的第三个参数有两个参数
lambda捕获和返回
当定义一个lambda时,编译器生成一个与lambda对应的新的类类型。
默认情况下,从lambda生成的类都包含一个对应该lambda所捕获的变量的数据成员。
lambda的值捕获
被捕获的变量的值是在lambda创建的时候被拷贝,而不是在调用时才去拷贝。
隐式捕获
可以让编译器根据lambda中的代码推断我们要使用哪些变量。为了指示编译器推断捕获列表。应该在捕获列表中写一个&或=。其中&告诉编译器采用捕获引用方式,=表示采用赋值方式
int temp;
auto iter = find_if(para.begin(),para.end(), [=] (const int b){return a >= temp});
可变lambda
默认情况下,对于一个值被拷贝的变量。lambda不会改变其值。若我们希望能改变一个被捕获的变量的值,就必须在参数列表首加关键字mutable
void func
{
size_t v = 10;
auto f = [v]() mutable {return v++};
}
lambda返回值
//error,编译器推断lambda返回void,但是其返回int
//即如果一个lambda体包含return之外的任何语句,则编译器假定其返回void。
transform(v.begin(), v.end(), v.begin(),
[](int i){if(i < 0) return -i; else return i;});
transform(v.begin(), v.end(), v.begin(),
[](int i) ->int {if(i < 0) return -i; else return i;});
参数绑定
除了lambda
bind函数可以解决find_if只接受带一个参数的predicate的问题。
bind可以看做是一个通用的函数适配器,他接受一个可以调用的对象,并生成一个新的可调用对象。
auto newCall = bind(call, arg_list);
- 当调用newCall时,newCall会调用call,并传递给他arg_list中的参数。
- arg_list中可能包含形如_n的名字,这些参数是占位符,表示newCall的参数。
//check6是一个可调用对象,接受一个string类型的参数
//用此string和6来调用check_size()
//此bind调用只有一个占位符,表示check6只接受单一参数。
//占位符出现在arg_list的第一个位置,表示check6的此参数对应check_size
//的第一个参数
auto check6 = bind(check_size, _1, 6)
int temp;
auto iter = find_if(para.begin(),para.end(), bind(check_size, _1, temp));
可以利用bind
sort(v.begin(), v.end(), isshorter);
sort(v.begin(), v.end(), bind(isshorter, _2, _1));
//进行反向比较