STL编程指南/函数对象概述
函数对象 Function Objects
概述
函数对象(Function Object),或者叫做仿函数Functor(这两个是同义词)是任何能够像函数一样被调用的对象。一个普通函数是一个函数对象,一个函数指针也是函数对象;更一般的讲,定义了()运算符的类的对象也是函数对象。
描述
基本的函数对象的概念有Generator, Unary Function和Binary Function,它们分别表示对象可以这样调用f(), f(x)及f(x,y)。(这个列表可以很容易扩展到三元函数,甚至更多,但是实际当中,没有一个STL算法需要超过两个参数的函数对象。)STL中定义的其他关于函数对象的概念都是这三个概念的refinement。
返回bool类型的函数对象是一种重要的特例。任何返回bool类型的Unary Function被称作Predicate,返回bool类型的Binary Function被称作Binary Predicate。
在函数对象和可适配的(adaptable)函数对象之间,有一个重要的但很细微的区别。[1] 一般来说,函数对象对于其参数的类型有限制。参数类型的限制可能并不简单,operator()可以重载,可以是成员模板函数,或者两者都是。相似的,程序没有办法确定参数的限制是什么。而adaptable函数对象指定参数和返回类型是什么,并提供了内嵌的类型定义,使这些类型有确定的名字并可以在程序中使用。如果类型F0是Adaptable Generator的一个模型,那么它必须定义F0::result_type。类似的;如果F1是一个Adaptable Unary Function的模型,那么它必须定义F1::argument_type和F1::result_type;如果F2是一个Adaptable Binary Function的模型,那么它必须定义F2::first_argument_type, F2::second_argument_type和F2::result_type。STL提供了基本类型unary_function和binary_function来简化Adaptable Unary Function和Adaptable Binary Function的定义。[2]
Adaptable函数对象是很重要的,因为它们可以被函数对象适配器adaptor使用。函数对象适配器是一种能够转换或者操作其他函数对象的函数对象。STL提供了很多函数对象适配器,包括unary_negate(返回一个特定的AdaptablePredicate的逻辑非),unary_compose和binary_compose,用来组合函数对象。
最后,STL还包含了很多预定义的函数对象,包括算术运算(plus, minus, multiplies, divides, modulus和negate),比较运算(equal_to, not_equal_to greater, less, greater_equal和less_equal)和逻辑运算(logical_and, logical_or, and logical_not)。这样不用自己写新的函数对象,只要组合预定义好的的函数对象和函数对象适配器,就可以进行很复杂的运算了。
例子
用随机数填充一个vector。在这个例子里面,函数对象就是一个函数指针。
vector<int> V(100);
generate(V.begin(), V.end(), rand);按照绝对值给double型的vector排序,也就是说忽略元素的符号。在这个例子里面,函数对象是是一个自定义类的对象。
struct less_mag : public binary_function<double, double, bool> {
bool operator()(double x, double y) { return fabs(x) < fabs(y); }
};
vector<double> V;
...
sort(V.begin(), V.end(), less_mag());计算一个vector的元素的合。在这个例子里面,函数对象是一个带有状态的自定义类的对象。
struct adder : public unary_function<double, void>
{
adder() : sum(0) {}
double sum;
void operator()(double x) { sum += x; }
};
vector<double> V;
...
adder result = for_each(V.begin(), V.end(), adder()); [3]
cout << "The sum is " << result.sum << endl;删除一个list里面所有大于100小于1000的元素。
list<int> L;
...
list<int>::iterator new_end =
remove_if(L.begin(), L.end(),
compose2(logical_and<bool>(),
bind2nd(greater<int>(), 100),
bind2nd(less<int>(), 1000)));
L.erase(new_end, L.end());概念
Generator
Unary Function
Binary Function
Predicate
Binary Predicate
Adaptable Generator
Adaptable Unary Function
Adaptable Binary Function
Adaptable Predicate
Adaptable Binary Predicate
类型
plus
minus
multiplies (formerly called times)
divides
modulus,
negate
equal_to
not_equal_to
greater
less
greater_equal
less_equal,
logical_and
logical_or
logical_not
subtractive_rng
identity
project1st
project2nd
select1st
select2nd
unary_function
binary_function
unary_compose
binary_compose
unary_negate
binary_negate
binder1st
binder2nd
pointer_to_unary_function
pointer_to_binary_function
函数
- compose1
- compose2
- not1
- not2
- bind1st
- bind2nd
- ptr_fun
备注
[1] 之所以称为”adaptable function object”可适配的函数对象,是因为它能够被函数对象适配器所使用。
[2] unary_function, binary_function和input_iterator, output_iterator, forward_iterator, bidirectional_iterator, random_access_iterator 是类似的: 它们是完全空的,只是提供了类型信息。
[3] 这只是展示如何使用函数对象的例子,并不建议这样计算vector元素的和。求和更好的方法是使用accumulate算法。