1、概论
如果类定义了调用运算符(即圆括号),则该类的对象称作函数对象(function object)。因为可以调用这种对象,所以我们说这些对象的"行为像函数一样"。
函数对象常常作为泛型算法的实参,并代替函数指针使用。以sort()为例,sort(begin,end)接受两个迭代器作为其参数,默认利用元素类型的<运算符来实现排序。sort(begin,end,comp)则以用户定义的comp函数作为元素比较的根据。通常情况下,可以设计自己的比较函数comp,然后以函数指针当做算法的一个参数。但是函数指针不能满足STL对抽象性的要求,同时函数指针无法和STL其他组件搭配,产生更灵活的变化,因此需要使用函数对象。
STL的函数对象,根据操作数的个数划分,可分为一元和二元函数对象。根据功能划分,可分为算术运算、关系运算、逻辑运算三大类,每个类分别定义了一个执行命名操作的调用运算符。
2、可适配(adaptable)的关键
STL的函数对象可以使算法更灵活,而更加灵活的关键,在于STL的函数对象的可适配性(adaptability)。STL的函数对象应该有能力被函数适配器修饰,彼此像积木一样地串接。为了拥有适配能力,每一个函数对象必须定义自己的相应类型,就像迭代器如果要融入STL,也必须依照规定定义自己的5个相应类型一样,这些相应类型是为了让适配器能够取出,获得函数对象的某些信息。
函数对象的相应类型主要用来表现函数参数类型和返回值类型。标准库在<stl_function.h>中定义了两个类,分别代表一元函数对象和二元函数对象,其中没有任何数据成员或成员函数,只有一些类型定义。
template <typename _Arg, typename _Result>
struct unary_function
{
/// @c argument_type is the type of the argument
typedef _Arg argument_type;
/// @c result_type is the return type
typedef _Result result_type;
};
template <typename _Arg1, typename _Arg2, typename _Result>
struct binary_function
{
/// @c first_argument_type is the type of the first argument
typedef _Arg1 first_argument_type;
/// @c second_argument_type is the type of the second argument
typedef _Arg2 second_argument_type;
/// @c result_type is the return type
typedef _Result result_type;
};
3、算术类函数对象
算术类函数对象包括:plus<Type>、minus<Type>、multiplies<Type>、divides<Type>、modulus<Type>、negate<Type>。
template <typename _Tp>
struct plus : public binary_function<_Tp, _Tp, _Tp>
{
_GLIBCXX14_CONSTEXPR
_Tp operator()(const _Tp &__x, const _Tp &__y) const
{
return __x + __y;
}
};
template <typename _Tp>
struct minus : public binary_function<_Tp, _Tp, _Tp>
{
_GLIBCXX14_CONSTEXPR
_Tp operator()(const _Tp &__x, const _Tp &__y) const
{
return __x - __y;
}
};
template <typename _Tp>
struct multiplies : public binary_function<_Tp, _Tp, _Tp>
{
_GLIBCXX14_CONSTEXPR
_Tp operator()(const _Tp &__x, const _Tp &__y) const
{
return __x * __y;
}
};
template <typename _Tp>
struct divides : public binary_function<_Tp, _Tp, _Tp>
{
_GLIBCXX14_CONSTEXPR
_Tp operator()(const _Tp &__x, const _Tp &__y) const
{
return __x / __y;
}
};
template <typename _Tp>