从零开始写STL—functional

function C++11 将任意类型的可调用(Callable)对象与函数调用的特征封装到一起。
这里的类是对函数策略的封装,将函数的性质抽象成组件,便于和algorithm库配合使用

基本运算符 和 基本比较符号组件

    template<class Arg, class Result>
    struct unary_function
    {
        typedef Arg argument_type;
        typedef Result 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;
    };

    template<class T>
    struct plus : binary_function<T, T, T>
    {
        T operator()(const T& x, const T& y) const
        {
            return x + y;
        }
    };

    template<class T>
    struct minus :binary_function<T, T, T>
    {
        T operator()(const T& x, const T& y) const
        {
            return x - y;
        }
    };

    template<class T>
    struct multiplies : binary_function<T, T, T>
    {
        T operator()(const T& x, const T& y) const
        {
            return x*y;
        }
    };

    template <class T>
    struct modulus : binary_function <T, T, T>
    {
        T operator() (const T& x, const T& y) const
        {
            return x%y;
        }
    };

    template<class T>
    struct negate :unary_function<T, T>
    {
        T operator()(const T& x) const
        {
            return -x;
        }
    };

    template<class T>
    struct less :binary_function<T, T, bool>
    {
        bool operator()(const T&lhs, const T& rhs) const
        {
            return lhs < rhs;
        }
    };
    
    template <class T>
    struct greater : binary_function<T, T, bool>
    {
        bool operator()(const T& lhs, const T& rhs) const
        {
            return lhs > rhs;
        }
    };

    template <class T> 
    struct equal_to : binary_function <T, T, bool>
    {
        bool operator() (const T& x, const T& y) const
        {
            return x == y;
        }
    };

    template<class T>
    struct greater_equal : binary_function<T, T, bool>
    {
        bool operator()(const T& lhs, const T& rhs)
        {
            return lhs >= rhs;
        }
    };

    template<class T>
    struct less_equal : binary_function<T, T, bool>
    {
        bool operator()(const T& lhs, const T& rhs)
        {
            return lhs <= rhs;
        }
    };

逻辑运算组件

对已经封装好的函数组件的运行结果增加一层封装。

    template <class Predicate>
    class unary_negate
        : public unary_function <typename Predicate::argument_type, bool>//参数类型是传入Predicate的参数类型,返回类型为bool
    {
    protected:
        Predicate fn;
    public:
        explicit unary_negate(const Predicate& pred) : fn(pred) {}
        bool operator() (const typename Predicate::argument_type& x) const
        {
            return !fn(x);
        }
    };

    template <class Predicate>
    class binary_negate
        : public binary_function<typename Predicate::first_argument_type, typename Predicate::second_argument_type, bool>
    {
    protected:
        Predicate fn;
    public:
        explicit binary_negate(const Predicate& pred) :fn(pred) {}
        bool operator() (const typename Predicate::first_argument_type& x,
            const typename Predicate::second_argument_type& y) const
        {
            return !fn(x, y);
        }
    };

参数绑定

将要调用的参数保存在结构中,调用的时候再传入
使用typename 和 模板 来指明返回类型 和 参数类型
建议使用explicit来避免隐式类型转换

    template<class Operation>
    class binder1st
        : public binary_function<typename Operation::first_argument_type, typename Operation::second_argument_type, typename  Operation::result_type>
    {
    protected:
        typename Operation::first_argument_type val;//要绑定的参数
        Operation op;
    public:
        explicit binder1st(const Operation& operation, const typename Operation::first_argument_type x) :op(operation),val(x) {}
        typename Operation::result_type operator()(const typename Operation::second_argument_type& xs)
        {
            return op(val, x);
        }
    };


    //绑定第二个参数
    template<class Operation>
    class binder2nd
        : public binary_function<typename Operation::first_argument_type, typename Operation::second_argument_type, typename  Operation::result_type>
    {
    protected:
        typename Operation::second_argument_type val;
        Operation op;
    public:
        explicit binder2nd(const Operation& operation, const typename Operation::second_argument_type x) :op(operation),val(x) {}
        typename Operation::result_type operator()(const typename Operation::first_argument_type& xs)
        {
            return op(x, val);
        }
    };

不定参数的绑定

底层数据 结构用tuple来实现,对于调用参数的获取,维护一个tuple index 模板类,去在模板中递归生成对应下标,这一部分涉及大量的模板元编程。

  • 为什么要生成所有参数的下标?
    需要知道参数的位置,顺序,这样对应着进行模板展开,从tuple中get出对应位置的参数传入函数进行调用
  • 如何生成?
    模板展开 + 模板偏特化
    template <std::size_t...>
    struct tuple_indices {};

    //生成下标 注意第二个模板是一个类模板 , 第一和第三个模板参数作为展开的边界
    template <std::size_t Sp, class IntTuple, std::size_t Ep>
    struct make_indices_imp;

    template <std::size_t Sp, std::size_t... Indices, std::size_t Ep>
    struct make_indices_imp<Sp, tuple_indices<Indices...>, Ep>
    {
        typedef typename make_indices_imp<Sp + 1, tuple_indices<Indices..., Sp>, Ep>::type type;
    };
    
    //对结束位置进行特化
    template <std::size_t Ep, std::size_t... Indices>
    struct make_indices_imp<Ep, tuple_indices<Indices...>, Ep>
    {
        typedef tuple_indices<Indices...> type;
    };

    template <std::size_t Ep, std::size_t Sp = 0>
    struct make_tuple_indices
    {
        typedef typename make_indices_imp<Sp, tuple_indices<>, Ep>::type type;
    };

具体tuple的内部实现改天再写。。。

    //绑定不定数目 不定类型的参数
    //底层数据通过tuple来保存实现
    要实现
    template <class F, class... Args>
    struct binder
    {
        //使用std::forward 进行完美转发
        //可见 http://en.cppreference.com/w/cpp/utility/forward
        binder(F&& f, Args&&... args) :data(std::forward<F>(f), std::forward<Args>(args)...) {}
        inline auto operator()()
        {
            typedef typename make_tuple_indices<std::tuple_size<std::tuple<F, Args...> >::value, 1>::type index_type;
            return run2(index_type());
        }
        template <std::size_t... Indices>
        void run2(tuple_indices<Indices...>)
        {
            //模板展开
            invoke(std::move(std::get<0>(data)), std::move(std::get<Indices>(data))...);
        }
        inline auto invoke(F&& f, Args&&... args)
        {
            //f 作为函数指针 ,args 作为参数传入
            return std::forward<F>(f)(std::forward<Args>(args)...);
        }
        //使用tuple来保存数据
        std::tuple<F,Args...> data;
    };
    

    template <class F, class... Args >
    ministl::binder<F,Args...> bind(F&& f, Args&&... args)
    {
        return binder<F, Args...>(std::forward<F>(f), std::forward<Args>(args)...);
    }

对类成员函数进行调用

大部分可以用lambda 代替,不过还是写一下,不作重点,精髓还是在于bind

template <class S, class T> mem_fun_t<S, T> mem_fun(S(T::*f)())
    {
        return mem_fun_t<S, T>(f);
    }

    template <class S, class T, class A>
    class mem_fun1_t : public binary_function <T*, A, S>
    {
        S(T::*pmem)(A);
    public:
        explicit mem_fun1_t(S(T::*p)(A)) : pmem(p) {}
        S operator() (T* p, A x) const
        {
            return (p->*pmem)(x);
        }
    };

    template <class S, class T, class A> mem_fun1_t<S, T, A> mem_fun(S(T::*f)(A))
    {
        return mem_fun1_t<S, T, A>(f);
    }

    template <class S, class T>
    class const_mem_fun_t : public unary_function <T*, S>
    {
        S(T::*pmem)() const;
    public:
        explicit const_mem_fun_t(S(T::*p)() const) : pmem(p) {}
        S operator() (T* p) const
        {
            return (p->*pmem)();
        }
    };

    template <class S, class T> const_mem_fun_t<S, T> mem_fun(S(T::*f)() const)
    {
        return const_mem_fun_t<S, T>(f);
    }

    template <class S, class T, class A>
    class const_mem_fun1_t : public binary_function <T*, A, S>
    {
        S(T::*pmem)(A) const;
    public:
        explicit const_mem_fun1_t(S(T::*p)(A) const) : pmem(p) {}
        S operator() (T* p, A x) const
        {
            return (p->*pmem)(x);
        }
    };

    template <class S, class T, class A> const_mem_fun1_t<S, T, A> mem_fun(S(T::*f)(A) const)
    {
        return const_mem_fun1_t<S, T, A>(f);
    }
    

    template <class S, class T>
    class mem_fun_ref_t : public unary_function <T, S>
    {
        S(T::*pmem)();
    public:
        explicit mem_fun_ref_t(S(T::*p)()) : pmem(p) {}
        S operator() (T& p) const
        {
            return (p.*pmem)();
        }
    };
    template<class S,class T,class A>
    class mem_fun1_ref_t : public binary_function<T, S, A>
    {
        S(T::*pmem)(A);
    public:
        explicit mem_fun1_ref_t(S(T::*p)(A)) :pmem(p) {}
        S operator()(T& p, A x) const
        {
            return (p.*pmem)(x);
        }
    };

    template <class S, class T>
    class const_mem_fun_ref_t : public unary_function <T, S>
    {
        S(T::*pmem)() const;
    public:
        explicit const_mem_fun_ref_t(S(T::*p)() const) : pmem(p) {}
        S operator() (T& p) const
        {
            return (p.*pmem)();
        }
    };

    template <class S, class T, class A>
    class const_mem_fun1_ref_t : public binary_function <T, A, S>
    {
        S(T::*pmem)(A) const;
    public:
        explicit const_mem_fun1_ref_t(S(T::*p)(A) const) : pmem(p) {}
        S operator() (T& p, A x) const
        {
            return (p.*pmem)(x);
        }
    };

    //Returns a function object that encapsulates member function f of type T.
    template <class S, class T>
    mem_fun_ref_t<S, T> mem_fun_ref(S(T::*f)())
    {
        return mem_fun_ref_t<S, T>(f);
    }

    template <class S, class T, class A>
    mem_fun1_ref_t<S, T, A> mem_fun_ref(S(T::*f)(A))
    {
        return mem_fun1_ref_t<S, T, A>(f);
    }

    template <class S, class T>
    const_mem_fun_ref_t<S, T> mem_fun_ref(S(T::*f)() const)
    {
        return const_mem_fun_ref_t<S, T>(f);
    }

    template <class S, class T, class A>
    const_mem_fun1_ref_t<S, T, A> mem_fun_ref(S(T::*f)(A) const)
    {
        return const_mem_fun1_ref_t<S, T, A>(f);
    }

转载于:https://www.cnblogs.com/joeylee97/p/8670888.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值