zoukankan      html  css  js  c++  java
  • STL源码分析--functional

    更多精彩内容,请关注微信公众号:后端技术小屋

    1 相关头文件

    functional
    functional.h
    stl_function.h 
    

    2 一元函数对象

    一元函数对象,是指这类函数对象只接受一个参数并返回一个参数。

    unary_function为STL中所有一元函数对象的基类。它定义了一元函数对象的输入/输出参数类型,其中argument_type为输入参数类型,result_type为输出参数类型,这两种类型由输入模板参数推导而来。

    template <class _Arg, class _Result>
    struct unary_function {
      typedef _Arg argument_type;
      typedef _Result result_type;
    };
    

    下面介绍几种有意思的一元函数对象。

    2.1 binder1st/binder2nd

    binder1st的功能:将某个参数值绑定到可调用对象(Callable type,函数对象/函数指针/std::function)的第一个参数中。同理,binder2nd将某个参数值绑定到可调用对象的第二个参数中。

    有了binder1st/binder2nd,便可利用已有的可调用对象生成各种变体,避免了重新定义带来的代码冗余。

        auto f = [](double a, double b){ return 2*(a+b); };
        double a0 = 1.0;
        double b0 = 2.0;
        auto uf1 = std::binder1st(f, a0);
        auto uf2 = std::binder2nd(f, b0);
        
        std::cout << uf1(3.0) << std::endl; // 执行f函数,参数1:被绑定的a0, 参数2: 3.0
        std::cout << uf2(4.0) << std::endl; // 执行f函数,参数1: 4.0,      参数2:被绑定的b0
    

    binder1st内部嵌套了一个可调用对象op。生成binder1st对象时,其内部记录传入的可调用对象和绑定参数。当执行operator()时,其调用可调用对象并返回结果。

    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:
      binder1st(const _Operation& __x,
                const typename _Operation::first_argument_type& __y)
          : op(__x), value(__y) {}
      typename _Operation::result_type
      operator()(const typename _Operation::second_argument_type& __x) const {
        return op(value, __x); 
      }
    };
    

    2.2 unary_compose

    将两个属于unary_function的函数对象级联。假设函数对象分别为op1op2, 那么unary_compose的执行结果为op1(op2(x))

    因此unary_compose的输入参数类型为_Operation2::argument_type,输出参数类型为_Operation1::result_type。并且要求在类型上_Operation2::result_type可隐式转换成_Operation1::argument_type

    template <class _Operation1, class _Operation2>
    class unary_compose
      : public unary_function<typename _Operation2::argument_type,
                              typename _Operation1::result_type> 
    {
    protected:
      _Operation1 _M_fn1;
      _Operation2 _M_fn2;
    public:
      unary_compose(const _Operation1& __x, const _Operation2& __y) 
        : _M_fn1(__x), _M_fn2(__y) {}
      typename _Operation1::result_type
      operator()(const typename _Operation2::argument_type& __x) const {
        return _M_fn1(_M_fn2(__x));
      }
    };
    

    2.3 pointer_to_unary_function

    将一个指向一元函数的指针封装成一元函数对象。

    template <class _Arg, class _Result>
    class pointer_to_unary_function : public unary_function<_Arg, _Result> {
    protected:
      _Result (*_M_ptr)(_Arg);
    public:
      pointer_to_unary_function() {}
      explicit pointer_to_unary_function(_Result (*__x)(_Arg)) : _M_ptr(__x) {}
      _Result operator()(_Arg __x) const { return _M_ptr(__x); }
    };
    

    2.4 mem_fun_t

    将类内非静态成员函数封装成一元函数对象。

    对于mem_fun_t对象,其构造时记录指向类_Tp内非静态成员函数(输入参数个数为零)的指针,执行时,传入指向_Tp对象的指针__p,调用(__p->*_M_f)()

    在C++中,函数指针类似这种形式:int (*f)(int, double)f指向一个入参为int, double,出参为int的函数。调用函数指针f时,只需指定输入参数。

    而成员函数指针类似于:int (T::*mf)(int, double)mf指向一个入参为int, double, 出参为int的成员函数。调用成员函数指针时,除了需指定输入参数外,还需指定T对象指针,因为类中非静态成员函数是和该类对象绑定的。

    template <class _Ret, class _Tp>
    class mem_fun_t : public unary_function<_Tp*,_Ret> {
    public:
      explicit mem_fun_t(_Ret (_Tp::*__pf)()) : _M_f(__pf) {}
      _Ret operator()(_Tp* __p) const { return (__p->*_M_f)(); }
    private:
      _Ret (_Tp::*_M_f)();
    };
    

    其他变体:

    • const_mem_fun_t: 将类内非静态的const成员函数封装成一元函数对象
    • mem_fun_ref_t: 类似mem_fun_t,区别在于调用mem_fun_t时传入的是类对象指针,而调用mem_fun_ref_t时传入的是类对象引用。
    • const_mem_fun_ref_t: const_mem_fun_tmem_fun_ref_t的组合

    2.5 其他

    • negate: 取负操作。实现中对_Tp对象执行operator-操作,因此negate的输入模板参数不止为数字,也可是重载了operator-操作符的其他任何类型。
    • logical_not: 逻辑取反。函数对象输入参数类型为_Tp, 输出参数类型为bool。实现中对_Tp对象执行operator!操作,对象可重载该操作符。
    • unary_negate: 同negate相似,只不过带了一个判断条件。输入参数__x, 返回布尔值!_M_pred(__x)

    3 二元函数对象

    二元函数对象接受两个参数,返回一个结果值。

    STL中定义的所有二元函数对象都继承自binary_function, 其中

    • first_argument_type: 第一个输入参数类型
    • second_argument_type: 第二个输入参数类型
    • result_type: 输出参数类型
    template <class _Arg1, class _Arg2, class _Result>
    struct binary_function {
      typedef _Arg1 first_argument_type;
      typedef _Arg2 second_argument_type;
      typedef _Result result_type;
    }; 
    

    3.1 mem_fun1_t

    mem_fun_t类似,将一个成员函数指针封装成函数对象。区别在于mem_fun_t中成员函数入参个数为零,而mem_fun1_t中成员函数入参个数为1,这样的话调用mem_fun1_t时,需同时传入成员函数的入参和成员函数所在类对象指针。

    其他变体:const_mem_fun1_t/mem_fun1_ref_t/const_mem_fun1_ref_t,功能与mem_fun_t的变体类似,这里跳过

    3.2 其他

    以下二元函数对象顾名思义,本质上是对各种操作符的封装。

    plus
    minus
    multiplies
    divides
    modulus
    equal_to
    not_equal_to
    greater
    less
    greater_equal
    less_equal
    logical_and
    logical_or
    logical_not 
    

    binary_compose: 功能同unary_compose。区别在于将三个二元函数对象级联,输出__fn1(__fn2(__x), __fn3(__x))

    推荐阅读

    更多精彩内容,请扫码关注微信公众号:后端技术小屋。如果觉得文章对你有帮助的话,请多多分享、转发、在看。
    二维码

  • 相关阅读:
    SpringBoot上传图片
    Java工具类(4) ------>运用easyexcel生成Excel表格
    SpringBoot(8) ------>集成SpringSecurity与Jwt
    docker_进阶
    jenkins基础
    C# 8 using declarations
    Sysmetric encryption and decryption via AES
    C# class implementation order of constructors include static constructor,constructor without modifiers and parameters, constructor with modifiers and parameters
    C# dictionary keys case insensitive
    Centos7安装Docker及运行hello-world
  • 原文地址:https://www.cnblogs.com/taiyang-li/p/14450529.html
Copyright © 2011-2022 走看看