NIUCLOUD是一款SaaS管理后台框架多应用插件+云编译。上千名开发者、服务商正在积极拥抱开发者生态。欢迎开发者们免费入驻。一起助力发展! 广告
# 第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; } }; ```