1. 程式人生 > >從零開始寫STL—functional

從零開始寫STL—functional

binder 保存 函數調用 mark 獲取 AR ref 返回 log

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 inddex 模板類,去在模板中遞歸生成對應下標。

    //綁定不定數目 不定類型的參數
    //底層數據通過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)...);
    }

從零開始寫STL—functional