Ch7 仿函数(另名 函数对象)

7.1 仿函数概观

仿函数在调用者可以像函数一样地被调用,在被调用者则以对象所定义的function call operator扮演函数的实质角色。

就实现观点而言,仿函数其实就是一个“行为类似函数”的对象。为了能够“行为类似函数”,其类别定义中必须自定义function call运算子(operator()),拥有这样的运算子之后,我们就可以在仿函数的对象后面加上一对小括号,以此调用仿函数所定义的operator(),如:

...
greater<int> ig;
ig(4,6);

greater<int>() (4,6);  //先产生一个临时对象,再指定参数
...

任何应用程序欲使用STL内建的仿函数,都必须含入<functional>头文件,SGI则将它们实际定义于<stl_function.h>文件中。

7.2 可配接(Adaptable)的关键

STL仿函数应该有能力被函数配接器修饰,为了拥有配接能力,每一个仿函数必须定义自己的相应型别,以便让配接器能够取出,获得仿函数的某些信息。

相应型别都只是一些typedef,所有必要操作在编译期就全部完成了,对程序的执行效率没有任何影响,不带来任何额外负担。

7.2.1 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,其用户便可以这样取得该仿函数的参数型别,并以相同手法取得其返回值型别:

//以下仿函数继承了unary_function
template <class T>
struct negate : public unary_function<T, T>{
    T operator() (const T& x ) const { return -x; }
};

//以下配接器用来表示某个仿函数的逻辑负值
template <class Predicate>
class unary_negate
    ...
public:
    bool operator() (const typename Predicate::argument_type& x) const {
        ...
    }
};

7.2.2 binary_function(二元函数)

binary_function用来呈现二元函数的第一参数型别、第二参数型别,以及返回值型别:

//STL规定,每个Adaptable Unary 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,其用户便可以这样取得该仿函数的各种参数型别

//以下仿函数继承了binary_function
template <class T>
struct plus : public binary_function<T, T, T>{
    T operator() (const T& x ,const T& y) const { return x+y; }
};

//以下配接器用来将某个二元仿函数转化为一元仿函数
template <class Operation>
class binder1st
    ...
protected:
    Operation op;
    typedef Operation::first_argument_type value;
public:
     typedef Operation::result_type
     bool operator() (const typename Operation::second_argument_type& x) const {
        ...
    }
};

7.3 算术类(Arithmetic)仿函数

以下是STL内建的“算术类仿函数”,除了“否定”运算为一元运算,其他都是二元运算。

  • 加法:plus<T>
  • 减法:minus<T>
  • 乘法:multiplies<T>
  • 除法:divides<T>
  • 模取(modulus):modulus<T>
  • 否定(negation):negate<T>

证同元素(identity element):

       所谓“运算op的证同元素”,意思是数字A若与该元素做op运算,会得到A自己。

       (加法的证同元素为0,因为任何元素加上0仍为自己;同理,乘法的证同元素为1。)

7.4 关系运算类(Relational)仿函数

以下是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 逻辑运算类(Logical)仿函数

以下是STL内建的“逻辑运算类仿函数”,其中And 和Or 为二元运算,Not 为一元运算。

  • 逻辑运算 And:logical_and<T>
  • 逻辑运算 Or:logical_or<T>
  • 逻辑运算 Not:logical_not<T>

7.6 证同(identify)、选择(select)、投射(project)

//证同函数。
//任何数值通过此函数后,不会有任何改变
//此式运用于<stl_set.h>,用来指定RB-tree所需的KeyOfValue op
//那是因为set元素的键值即实际值,所以采用identity
template <class T>
struct identity : public unary_function<T, T> {
    const T& operator() (const T& x) const { return x; }
};

//选择函数1。
//接收一个pair,传回其第一元素
//此式用于<stl_map.h>,用来指定RB-tree所需的KeyOfValue op
//由于map是以pair元素的第一元素为其键值,所以采用select1st
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;
    }
};

//选择函数2。
//接收一个pair,传回其第二元素
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;
    }
};

//投射函数1。
//传回第一参数,忽略第二参数
template <class Arg1, class Arg2>
struct project1st : public binary_fucntion<Arg1, Arg2, Arg1>{
    Arg1 operator() (const Arg1& x, const Arg2&) const { return x; }
};

//投射函数2.
//传回第二参数,忽略第一参数
template <class Arg1, class Arg2>
struct project2nd : public binary_function<Arg1, Arg2, Arg2>{
    Arg2 operator() (const Arg1&, const Arg2& y) const { return y; }
};
posted @ 2017-02-10 11:38  &ATM  阅读(257)  评论(0编辑  收藏  举报
……