<tbody id="xj1oc"></tbody>

    <bdo id="xj1oc"></bdo><bdo id="xj1oc"><optgroup id="xj1oc"><thead id="xj1oc"></thead></optgroup></bdo>

    現在的位置: 首頁 > 黃專家專欄 > 正文

    Boost – Function 分析

    2014年10月30日 黃專家專欄 ⁄ 共 7168字 ⁄ 字號 評論關閉

    本文假設了解 boost::function 相關用法

    首先需要包含的頭文件為 boost/function.hpp

    里面內容比較簡單

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #  if BOOST_FUNCTION_MAX_ARGS >= 0
    #    include <boost/function/function0.hpp>
    #  endif
    #  if BOOST_FUNCTION_MAX_ARGS >= 1
    #    include <boost/function/function1.hpp>
    # endif
    #  if BOOST_FUNCTION_MAX_ARGS >= 2
    #    include <boost/function/function2.hpp>
    #  endif
    #  if BOOST_FUNCTION_MAX_ARGS >= 3
    #    include <boost/function/function3.hpp>
    #  endif
    ... ...

    默認的 BOOST_FUNCTION_MAX_ARGS 為 10,說明最大支持為10個參數

    那么,可以知道引入了function0 ~ function10 共11個文件

    第N個文件都是定義了支持 N 個參數的 function 類

    我們以參數 BOOST_FUNCTION_MAX_ARGS = 4 來看看定義

    boost/function/function4.hpp 頭文件里只有這樣幾行

    1
    2
    3
    #define BOOST_FUNCTION_NUM_ARGS 4
    #include <boost/function/detail/maybe_include.hpp>
    #undef BOOST_FUNCTION_NUM_ARGS

    boost/function/detail/maybe_include.hpp 里面其實就定義了 BOOST_FUNCTION_N

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #if BOOST_FUNCTION_NUM_ARGS == 0
    #  ifndef BOOST_FUNCTION_0
    #    define BOOST_FUNCTION_0
    #    include <boost/function/function_template.hpp>
    #  endif
    #elif BOOST_FUNCTION_NUM_ARGS == 1
    #  ifndef BOOST_FUNCTION_1
    #    define BOOST_FUNCTION_1
    #    include <boost/function/function_template.hpp>
    #  endif
    #elif BOOST_FUNCTION_NUM_ARGS == 2
    #  ifndef BOOST_FUNCTION_2
    #    define BOOST_FUNCTION_2
    #    include <boost/function/function_template.hpp>
    #  endif
    ... ...

    boost/function/function_template.hpp 首先看兩個宏定義

    1
    2
    #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
    #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)

    BOOST_FUNCTION_NUM_ARGS 就是當前文件支持的參數個數,當前是4 BOOST_FUNCTION_TEMPLATE_PARMS 是宏自身擴展,展開時可能如下:

    1
    2
    3
    4
    #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
      // typename T0 , typename T1 , typename T2 , typename T3
      // 同樣 BOOST_FUNCTION_TEMPLATE_ARGS 展開如下
      // T0 , T1 , T2 , T3

    可以看到,我們用宏展開后的結果,function里都是一些構造函數和賦值函數,所以應該主要工作都在基類中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    template<typename R , typename T0 , typename T1 , typename T2 , typename T3>
    class function<R ( T0 , T1 , T2 , T3)> : public function4<R , T0 , T1 , T2 , T3> {
      typedef function4<R , T0 , T1 , T2 , T3> base_type;
      typedef function self_type;
      struct clear_type {};
      public:
      function() : base_type() {}
    
      // 模板的 sfinae 原則,避免整數被選入
      template<typename Functor>
        function(Functor f,
            typename enable_if_c<
            (boost::type_traits::ice_not<
             (is_integral<Functor>::value)>::value),
            int>::type = 0) : base_type(f) {}
      template<typename Functor,typename Allocator>
    
        // 同上
        function(Functor f, Allocator a,
            typename enable_if_c<(
              boost::type_traits::ice_not<(
                is_integral<Functor>::value)>::value),int>::type = 0) :
          base_type(f,a) {}
      function(clear_type*) : base_type() {}
      function(const self_type& f) : base_type(static_cast<const base_type&>(f)) {}
      function(const base_type& f) : base_type(static_cast<const base_type&>(f)) {}
      self_type& operator=(const self_type& f) {
        self_type(f).swap(*this);
        return *this;
      }
      template<typename Functor>
        typename enable_if_c<(boost::type_traits::ice_not<
            (is_integral<Functor>::value)>::value),
                 self_type&>::type
                   operator=(Functor f) {
                     self_type(f).swap(*this);
                     return *this;
                   }
      self_type& operator=(clear_type*) {
        this->clear();
        return *this;
      }
      self_type& operator=(const base_type& f) {
        self_type(f).swap(*this);
        return *this;
      }
    }

    所看看它基類的內容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    template<typename R , typename T0 , typename T1 , typename T2 , typename T3>
    class function4 : public function_base
    {
      public:
        typedef R result_type;
        typedef boost::detail::function::basic_vtable4<R , T0 , T1 , T2 , T3> vtable_type;
    
        struct clear_type {};
        template<typename Functor>
          function4(Functor f,
              typename enable_if_c<(boost::type_traits::ice_not<
                (is_integral<Functor>::value)>::value), int>::type = 0) {
            this->assign_to(f);
          }
    
        // 主要賦值在這個函數
        template<typename Functor>
          void assign_to(Functor f) {
            using detail::function::vtable_base;
    
            // 以下兩行是得到 Functor 的類型
            // 這個是由 tag 做萃取器的
            typedef typename detail::function::get_function_tag<Functor>::type tag;
            typedef detail::function::get_invoker4<tag> get_invoker;
            typedef typename handler_type::invoker_type invoker_type;
            typedef typename get_invoker::template apply<Functor, R ,T0 , T1 , T2 , T3> handler_type;
    
            // vtable_type 負責實際 Functor 映射到內部 function_buffer 的管理
            // 這里之所以用靜態的是因為同一種類型的 assign_to都是一樣的策略
            // 不同 Functor 自然生成不同的 assign_to,那么 stored_vtable 也自然不同了
            static vtable_type stored_vtable =
            { { &manager_type::manage }, &invoker_type::invoke };
            if (stored_vtable.assign_to(f, functor)) {
              std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
              if (boost::has_trivial_copy_constructor<Functor>::value &&
                  boost::has_trivial_destructor<Functor>::value &&
                  detail::function::function_allows_small_object_optimization<Functor>::value) {
                value |= (std::size_t)0x01;
                vtable = reinterpret_cast<detail::function::vtable_base *>(value);
              } else {
                vtable = 0;
              }
            }
          }
        ... ...
    }

    上面看有兩個成員變量是比較重要的,一個是 vtable, 一個是 function

    他們都在基類 function_base 中被描述

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    class function_base {
      ... ...
        detail::function::vtable_base* vtable;
      // 真正存儲的指針
      mutable detail::function::function_buffer functor;
    };
    
    union function_buffer {
      mutable void* obj_ptr;  // 對象指針類型
      mutable void (*func_ptr)(); // 函數指針類型
    
      // 指針本身的類型, 比如是const約束? volite約束?
      struct type_t {
        const detail::sp_typeinfo* type;
        bool const_qualified;
        bool volatile_qualified;
      } type;
    
      // 成員函數指針的結構
      struct bound_memfunc_ptr_t {
        void (X::*memfunc_ptr)(int);
        void* obj_ptr;
      } bound_memfunc_ptr;
    
      // 對象引用類型
      struct obj_ref_t {
        mutable void* obj_ptr;
        bool is_const_qualified;
        bool is_volatile_qualified;
      } obj_ref;
    
      // 小函數對象的優化
      // 如果是小函數對象,那么直接構造在這個 union 上
      mutable char data;
    };
    
    // 這個是干嘛用的現在還不清楚
    struct vtable_base {
      void (*manager)(const function_buffer& in_buffer,
          function_buffer& out_buffer,
          functor_manager_operation_type op);
    };

    萃取器的 tag 代碼如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    struct function_ptr_tag {};
    struct function_obj_tag {};
    struct member_ptr_tag {};
    struct function_obj_ref_tag {};
    
    template<typename F>
    class get_function_tag {
      // 這是個依次迭代的關系
      // 巧妙啊,這樣解決了定義 type 為不同類型的問題
      // 其實是一個 if-else 的編譯期選擇綁定
      typedef typename mpl::if_c<(is_pointer<F>::value),
              function_ptr_tag,
              function_obj_tag>::type ptr_or_obj_tag;
      typedef typename mpl::if_c<(is_member_pointer<F>::value),
              member_ptr_tag,
              ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
      typedef typename mpl::if_c<(is_reference_wrapper<F>::value),
              function_obj_ref_tag,
              ptr_or_obj_or_mem_tag>::type or_ref_tag;
      public:
      typedef or_ref_tag type;
    };
    
    // vtable_type 大概代碼如下
    typedef boost::detail::function::basic_vtable0<R> vtable_type;
    template<typename R >
    struct basic_vtable4
    {
      template<typename F>
        bool assign_to(F f, function_buffer& functor) {
          typedef typename get_function_tag<F>::type tag;
          return assign_to(f, functor, tag());
        }
    
      // 以下重載了幾種 tag
      // 普通指針對象
      template<typename FunctionPtr>
        bool assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) {
          this->clear(functor);
          if (f) {
            // 普通函數指針都是轉換成 (void (*)())(f) 指針
            functor.func_ptr = (void (*)())(f);
            return true;
          } else {
            return false;
          }
        }
    
      // 仿函數對象
      template<typename FunctionObj>
        bool assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) {
          if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
            // 小對象優化
            assign_functor(f, functor,
                mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
            return true;
          } else {
            return false;
          }
        }
    
      // 具體的小對象優化
      template<typename FunctionObj>
        void assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) {
          functor.obj_ptr = new FunctionObj(f);
        }
    
      template<typename FunctionObj>
        void assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) {
          new ((void*)&functor.data) FunctionObj(f);
        }
    };

    最后調用一目了然了

    1
    2
    3
    4
    5
    6
    inline function4<R , T0 , T1 , T2 , T3>::operator()( T0 a0 , T1 a1 , T2 a2 , T3 a3) const {
      if (this->empty())
        boost::throw_exception(bad_function_call());
      return get_vtable()->invoker
        (this->functor , a0 , a1 , a2 , a3);
    }

    抱歉!評論已關閉.

    黄色电影网址