1. 仿函数的概念
仿函数(functors)是早期的命名,c++标准规格定案后所采用的新名称是函数对象(function objects)。仿函数是一个能行使函数功能的类,必须重载operator()运算符,调用仿函数,就是通过类对象调用重载后的operator运算符。
2. 仿函数的主要作用
以stl中的仿函数为例,stl中的提供的算法,往往有两个版本,一个是最直观的某种运算,另一种是泛化的演算流程,允许用户"以template参数来指定所要采行的策略",仿函数通常用于指定某种操作来当作算法的参数,流程是通过仿函数产生一个对象,通过此对象作为该算法的参数。
通过上述描述,可以看出仿函数其实是给算法提供一种策略,使得stl算法更加灵活,而灵活的关键,在于stl仿函数的可配接行。
例如标准库中的find函数:
template <class InputIterator, Class T>
InputIterator find(InputIterator first,
InputIterator last,
const T& value)
{
while (first != last && *first != value)
++first;
return first;
}
//Predicate为仿函数
template <class InputIterator, class Predicate>
InputIterator find(InputIterator first,
InputIterator last,
Predicate pred)
{
while (first != last && !pred(*first))
++first;
return first;
}
3. stl仿函数的分类
以操作数(operand)的个数划分,分为一元和二元仿函数;
以功能划分,可分为算数运算(Arithmetic)、关系运算(Rational)和逻辑运算(Logical);
4. 按操作数划分
4.1 unary_function
unary_function用来呈现一元函数的参数型别和返回值型别。定义如下:
template <class Arg, class Result>
struct unary_function
{
typedef Arg argument_type;
typedef Result result_type;
};
//negate继承了unary_function
template <class T>
struct negate : public unary_function<T, T> {
T operator() (const T& x) const { return -x; }
};
//配接器表示某个仿函数的逻辑负值
template <class Predicate>
struct unary_negate
{
...
public:
bool operator() (const typename Predicate::argument_type& x) {
...
}
};
4.2 binary_function
binary_function用来呈现二元函数的第一参数的型别,第二参数的型别以及回返值型别。其定义如下:
template <class Arg1, class Arg2, class Result>
struct binary_function
{
typedef Arg1 first_argument_type;
typedef Arg2 second_argument_type;
typedef Result result_type;
};
template <class T>
struct plus : public binary_function<T, T, T> {
T operator() (const T& x, const T& y) const { return x + y; }
};
//配接器(adapter)将二元仿函数转化为一元仿函数
template <class Operation>
struct binary1st
{
...
protected:
Operation op;
typename Operation::first_argument_type value;
public:
typename Operation::result_type
operator() (const typename Operation::second_argument_type& x) const {
...
}
};
仿函数继承unary_function或者binary_function的意义: 可适配adaptable, 便于Function Adapt(适配器)“提问问题”(通过typedef的参数回答),后续将继续展开。
5. 按功能划分
5.1 算数类仿函数
加法: plus<T>
减法: minus<T>
乘法: multiplies<T>
除法: divides<T>
模取(modules): modules<T>
否定(negation): negate<T>
eg:
template <class T>
struct plus : public binary_function<T, T, T> {
T operator() (const T& x, const T& y) const { return x + y; }
};
5.2 关系运算类仿函数
等于(equality): equal_to<T>
不等于: not_equal_to<T>
大于: greater<T>
大于或等于: greater_equal<T>
小于: less<T>
小于或等于: less_equal<T>
eg:
template <class T>
struct equal_to : public binary_function<T, T, bool> {
T operator() (const T& x, const T& y) const { return x == y; }
};
5.3 逻辑运算仿函数
逻辑运算And: logical_and<T>
逻辑运算Or: logical_or<T>
逻辑运算Not: Loical_not<T>
eg:
template <class T>
struct logical_and : public binary_function<T, T, bool> {
T operator() (const T& x, const T& y) const { return x && y; }
};
6. stl仿函数使用实例
使用stl中的sort对一个int型数组进行排序。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
bool myFunc(int i, int j)
{
return (i < j);
}
struct myclass
{
bool operator() (int i, int j)
{
return (i < j);
}
}myObj;
int main()
{
int a[] = { 21,23,11,13,56,12,47,29 };
vector<int> myvec(a, a + 8);
sort(myvec.begin(), myvec.begin() + 4);
sort(myvec.begin() + 4, myvec.end(), myFunc);
sort(myvec.begin(), myvec.end(), myObj);
sort(myvec.rbegin(), myvec.rend());
system("pause");
return 0;
}