# 第7章 仿函数
## 7.1 仿函数(functors)概观
仿函数(functors)是早起的命名,C++ 标准规格定案后采用的新名称是函数对象(function object),它是一种具有函数特质的对象。
STL 使用仿函数的原因:函数指针不能满足 STL 对抽象性的要求,也不能满足软件积木的要求,即函数指针无法和STL其它组件搭配。
仿函数其实上就是一个“行为类似函数”的对象,其类别定义中必须自定义 function call 运算子(`operator()`)。
STL 仿函数的分类,若以操作数(operand)的个数划分,可分为一元和二元的仿函数,若以功能划分,可分为算术运算符(Arithmetic)、关系运算(Rational)、逻辑运算(Logical)三大类。
## 7.2 可配接(Adaptable)的关键
STL 仿函数应该有能力被函数配接器(function adapter)修饰,为了拥有配接能力,每一个仿函数必须定义自己的相应型别(associative types)。
`unary_function` 用来呈现一元函数的参数型别和回返值型别:
``` c++
template <class Arg, class Result>
struct unary_function {
typedef Arg argument_type;
typedef Result result_type;
};
tmplate <class T>
struct negate : public unary_function<T, T> {
T operator()(const T& x) const { return -x; }
};
```
`binary_function` 用来呈现二元函数的第一参数型别、第二参数型别以及回返值型别。
## 7.3 算术类仿函数
STL 内建的“算术类仿函数”,支持加法、减法、乘法、除法、模数和否定运算,除了否定运算,其它都是二元运算。
* 加法:`plus<T>`
* 减法:`minus<T>`
* 乘法:`multiplies<T>`
* 除法:`divides<T>`
* 模取:`modulus<T>`
* 否定:`negate<T>`
## 7.4 关系运算类仿函数
STL 内建的“关系运算类仿函数”支持了等于、不等于、大于、大于等于、小于、小于等于六种运算,均为二元运算。
* 等于(equality):`equal_to<T>`
* 不等于(inequality):`not_equal_to<T>`
* 大于(greater than):`greater<T>`
* 大于或等于(greater than or equal):`greater_equal<T>`
* 小于(less than):`less<T>`
* 小于或等于(less than or equal):`less_equal<T>`
## 7.5 逻辑运算类仿函数
STL 内建的“逻辑运算类仿函数”支持了逻辑运算中的 And、Or、Not 三种运算,其中 Not 为一元运算。
* 逻辑运算 And:`logical_and<T>`
* 逻辑运算 Or:`logical_or<T>`
* 逻辑运算 Not:`logical_not<T>`
## 7.6 证同(identity)、选择(select)、投射(project)
证同函数(identity function),任何数值通过此函数后,不会有任何改变。
``` c++
struct identity : public unary_function<T, T> {
const T& operator()(const T& x) const { return x; }
};
```
选择函数(selection function),接受一个 pair,传回第一或第二元素。
``` c++
template <class Pair>
struct select1st : public unary_function<Pair, typename Pair::fist_type> {
const typename Pair::fist_type& operator()(const Pair& x) const {
return x.first;
}
};
```
投射函数(project function),返回第一或第二参数。
``` c++
template <class Arg1, class Arg2>
struct project2nd : public binary_function<Arg1, Arg2, Arg1> {
Arg2 operator()(consgt Arg1&, const Arg2& y) const {
return y;
}
};
```
