• 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; }
    };
  • 相关阅读:
    zoj 3195 Design the city LCA Tarjan
    hdu 2586 How far away ? 离线LCA
    洛谷 P3379 【模板】最近公共祖先(LCA)Tarjan离线
    codeforces #446 892A Greed 892B Wrath 892C Pride 891B Gluttony
    设计模式(16)---原型模式
    设计模式(15)---享元模式
    设计模式(14)---组合模式
    设计模式(13)---外观模式
    设计模式(12)---适配器模式
    设计模式(11)---代理模式
  • 原文地址:https://www.cnblogs.com/atmacmer/p/6385651.html
Copyright © 2020-2023  润新知