仿函数概况
仿函数(functors)是早期的命名,C++标准规格定案后的新名称是函数对象(function objects)。
仿函数主要作用于STL所提供的各种算法,从【STL】算法可以看出算法多版本多功能,离不开仿函数的支持。
就现在而言,仿函数其实就是一个“行为类似函数”的对象。为了实现这个行为,类别定义中必须自定义(重载)function call 运算子(operator() )。这时候就可以使用下面两种用法:
第一种就是产生一个临时对象,然后指定参数,类似下面这种:
greater<int>()(6,4);
第二种不常见,但是一种主流用法:
可配接的关键
为了实现算法的泛化,以及整个库的复用性。STL仿函数也应该具备能力被函数配接器修饰。每一个仿函数必须定义自己的相应型别,为了能够让配接器取出,获取仿函数信息。
仿函数的相应型别主要用来表现函数参数型别和传回值型别。为了方便,定义了两个classes,分别代表一元仿函数和二元仿函数,没有任何data members 或 member functions,只有一些型别定义。任何仿函数,只需要根据个人需求继承,即可得到相应型别,同时就具备了配接能力。
unary_function
unary_function用来呈现一元函数的参数型别和回返值型别。STL规定,每一个Adaptable Unary Function都应该继承此类别,其定义十分简单:
template <class _Arg, class _Result>
struct unary_function {
typedef _Arg argument_type;
typedef _Result result_type;
};
一旦某个仿函数继承了unary_function,用户便可取得该仿函数的参数型别,并以相同手法取得其返回型别。
template <class _Tp>
struct negate : public unary_function<_Tp,_Tp>
{
_Tp operator()(const _Tp& __x) const { return -__x; }
};
template <class _Predicate>
class unary_negate: public unary_function<typename _Predicate::argument_type, bool> {
public:
bool operator()(const typename _Predicate::argument_type& __x) const {
...
}
};
binary_function
binary_function用来呈现二元函数的第一参数型别、第二参数型别,以及回返值型别。STL规定,每一个Adaptable 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;
};
一旦某个仿函数继承了Binary_function,其用户即可取到该仿函数的各种型别:
template <class _Tp>
struct plus : public binary_function<_Tp,_Tp,_Tp> {
_Tp operator()(const _Tp& __x, const _Tp& __y) const { return __x + __y; }
};
template <class _Operation>
class binder1st: public unary_function<typename _Operation::second_argument_type,typename _Operation::result_type> {
protected:
_Operation op;
typename _Operation::first_argument_type value;
public:
typename _Operation::result_type
operator()(const typename _Operation::second_argument_type& __x) const {
...
}
};
算术类、关系运算类、逻辑运算类仿函数
类别 | 算法 |
---|---|
算术类 | 加法、减法、乘法、除法、模取、否定 |
关系运算类 | 等于、不等于、大于、大于或等于、小于、小于或等于 |
逻辑运算类 | And、Or、Not |
证同(identity)、选择(select)、投射(project)
这些仿函数都只是将其参数原封不动地传回。其中某些仿函数对传回参数有刻意的选择,或是刻意的忽略。
template <class _Tp>
struct _Identity : public unary_function<_Tp,_Tp> {
const _Tp& operator()(const _Tp& __x) const { return __x; }
};
template <class _Tp> struct identity : public _Identity<_Tp> {};
// select1st and select2nd are extensions: they are not part of the standard.
template <class _Pair>
struct _Select1st : public unary_function<_Pair, typename _Pair::first_type> {
const typename _Pair::first_type& operator()(const _Pair& __x) const {
return __x.first;
}
};
template <class _Pair>
struct _Select2nd : public unary_function<_Pair, typename _Pair::second_type>
{
const typename _Pair::second_type& operator()(const _Pair& __x) const {
return __x.second;
}
};
template <class _Pair> struct select1st : public _Select1st<_Pair> {};
template <class _Pair> struct select2nd : public _Select2nd<_Pair> {};
// project1st and project2nd are extensions: they are not part of the standard
template <class _Arg1, class _Arg2>
struct _Project1st : public binary_function<_Arg1, _Arg2, _Arg1> {
_Arg1 operator()(const _Arg1& __x, const _Arg2&) const { return __x; }
};
template <class _Arg1, class _Arg2>
struct _Project2nd : public binary_function<_Arg1, _Arg2, _Arg2> {
_Arg2 operator()(const _Arg1&, const _Arg2& __y) const { return __y; }
};
template <class _Arg1, class _Arg2>
struct project1st : public _Project1st<_Arg1, _Arg2> {};
template <class _Arg1, class _Arg2>
struct project2nd : public _Project2nd<_Arg1, _Arg2> {};