#眉標=Boost #副標=「Boost技術與應用」系列文章(7) #大標= Boost.Function內核剖析 #作者=文/圖 侯捷 #圖1 此程式示範使用Boost.Function。注意它含入============= 。 #include #include //足以以一當十(所謂十是指下面這些寫法) //#include //直接根據需要這樣含入也可以 //#include //依此類推... using namespace std; using namespace boost; int func1(int i) { return (i*5); } bool func2(int i, double d) { return (i > d); } int main() { function1 f1; //(1) f1 = &func1; cout << f1(10) << endl; //50 function2 f2; //(2) f2 = &func2; cout << f2(10, 1.1) << endl; //1 return 0; } ================ #圖2 function.hpp源碼摘錄。定義BOOST_FUNCTINO_MAX_ARGS為10,並逐一含入functionN.hpp。 ============= #include #include #ifndef BOOST_FUNCTION_MAX_ARGS # define BOOST_FUNCTION_MAX_ARGS 10 #endif // BOOST_FUNCTION_MAX_ARGS … // Visual Age C++ doesn't handle the file iteration well #if BOOST_WORKAROUND(__IBMCPP__, >= 500) # if BOOST_FUNCTION_MAX_ARGS >= 0 # include # endif # if BOOST_FUNCTION_MAX_ARGS >= 1 # include # endif # if BOOST_FUNCTION_MAX_ARGS >= 2 # include # endif # if BOOST_FUNCTION_MAX_ARGS >= 3 # include # endif … # if BOOST_FUNCTION_MAX_ARGS >= 10 # include # endif #else // What is the '3' for? # define BOOST_PP_ITERATION_PARAMS_1 (3,(0,BOOST_FUNCTION_MAX_ARGS,)) # include BOOST_PP_ITERATE() # undef BOOST_PP_ITERATION_PARAMS_1 #endif ================ ==<灰>=========== # define BOOST_FUNCTION_MAX_ARGS 10 ================ #圖3 的內容。 ============= #define BOOST_FUNCTION_NUM_ARGS 2 #include #undef BOOST_FUNCTION_NUM_ARGS ================ #圖4 的內容。 ============= #define BOOST_FUNCTION_NUM_ARGS 3 #include #undef BOOST_FUNCTION_NUM_ARGS ================ #圖5 的內容。 ============= #define BOOST_FUNCTION_NUM_ARGS 4 #include #undef BOOST_FUNCTION_NUM_ARGS ================ #圖6 源碼摘錄。 ============= #if BOOST_FUNCTION_NUM_ARGS == 0 # ifndef BOOST_FUNCTION_0 # define BOOST_FUNCTION_0 # include # endif #elif BOOST_FUNCTION_NUM_ARGS == 1 # ifndef BOOST_FUNCTION_1 # define BOOST_FUNCTION_1 # include # endif #elif BOOST_FUNCTION_NUM_ARGS == 2 # ifndef BOOST_FUNCTION_2 # define BOOST_FUNCTION_2 # include # endif #elif BOOST_FUNCTION_NUM_ARGS == 3 … (註:直到BOOST_FUNCTION_NUM_ARGS == 50) #else # error Cannot handle Boost.Function objects that accept more than 50 arguments! #endif ================ #圖7 function_template.hpp源碼摘錄,主要列出class template的定義式。 ============= template< typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR > class BOOST_FUNCTION_FUNCTION : public function_base { public: #ifndef BOOST_NO_VOID_RETURNS typedef R result_type; #else typedef typename detail::function::function_return_type::type result_type; #endif // BOOST_NO_VOID_RETURNS #if BOOST_FUNCTION_NUM_ARGS == 1 typedef T0 argument_type; #elif BOOST_FUNCTION_NUM_ARGS == 2 typedef T0 first_argument_type; typedef T1 second_argument_type; #endif BOOST_FUNCTION_FUNCTION() : function_base(), invoker(0) {} ~BOOST_FUNCTION_FUNCTION() { clear(); } ... typedef result_type (*invoker_type)(detail::function::any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS); invoker_type invoker; }; ================ ===<反灰>============= class BOOST_FUNCTION_FUNCTION : public function_base ================ #圖8 BOOST_FUNCTION_FUNCTION是個巨集,定義於function_template.hpp。 ============= #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS) ================ #圖9 BOOST_JOIN又是個巨集,定義於boost\config\suffix.hpp。 ============= #define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y ) #define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2(X,Y) #define BOOST_DO_JOIN2( X, Y ) X##Y ================ ===<反灰>============= #define BOOST_JOIN( X, Y ) X##Y ================ ===<反灰>============= #include ================ ===<反灰>============= #include ================ ===<反灰>============= #define BOOST_FUNCTION_NUM_ARGS 2 ================ ===<反灰>============= # define BOOST_FUNCTION_2 ================ #圖10 class template function2的定義式摘錄。 ============= template< typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR > class function2 : public function_base { public: ... typedef T0 first_argument_type; typedef T1 second_argument_type; function2() : function_base(), invoker(0) {} ~function2() { clear(); } ... typedef result_type (*invoker_type)(detail::function::any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS); invoker_type invoker; }; ================ #圖11 BOOST_FUNCTION_COMMA被定義於============= boost\function\function_template.hpp。 // Comma if nonzero number of arguments #if BOOST_FUNCTION_NUM_ARGS == 0 (註:目前其值為2,所以走下一語句) # define BOOST_FUNCTION_COMMA #else # define BOOST_FUNCTION_COMMA , #endif // BOOST_FUNCTION_NUM_ARGS > 0 ================ #圖12 BOOST_FUNCTION_DEFAULT_ALLOCATOR被定義於function_ template.hpp。其內判斷BOOST_NO_STD_ALLOCATOR,此名稱在Boost的許多.hpp中針對各種編譯器版本和/或各種標準庫版本都有定義。這裡不討論那些版本,直接告訴你,VC6.0採用灰色那個語句,定義為int。 ============= 註:in boost\function\function_template.hpp // Type of the default allocator #ifndef BOOST_NO_STD_ALLOCATOR # define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator #else # define BOOST_FUNCTION_DEFAULT_ALLOCATOR int #endif // BOOST_NO_STD_ALLOCATOR ================ #圖13 BOOST_FUNCTION_TEMPLATE_PARMS定義於function_template.hpp。 ============= #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) 註1:以上會根據BOOST_FUNCTION_NUM_ARGS為n而演繹出 typename T0, typename T1, typename T2,…,typename Tn-1, 註2:另有BOOST_FUNCTION_PARMS會根據n演繹出 T0 a0, T1 a1, T2 a2,…,Tn-1 an-1 ================ #圖14 BOOST_FUNCTION_TEMPLATE_ARGS定義於function_template.hpp。 ============= #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T) 註1:以上會根據BOOST_FUNCTION_NUM_ARGS為n而演繹出 T0, T1, T2,…Tn-1 註2:另有BOOST_FUNCTION_ARGS會根據n演繹出 a0, a1, a2,…, an-1 ================ #圖15 function_template.hpp中的class template被預處理之後獲得的結果(當被指涉函式的引數個數為2時)。 ============= template< typename R, typename T0, typename T1, typename Allocator = int > class function2 : public function_base { public: typedef R result_type; //註:此行的分析在後頭 typedef T0 first_argument_type; typedef T1 second_argument_type; function2() : function_base(), invoker(0) {} ~function2() { clear(); } … typedef result_type (*invoker_type)(detail::function::any_pointer, T0, T1); invoker_type invoker; }; ================ ===<反灰>============= function2 f2; ================ ===<反灰>============= typedef bool result_type; typedef int first_argument_type; typedef double second_argument_type; ================ ===<反灰>============= #ifndef BOOST_NO_VOID_RETURNS typedef R result_type; #else typedef typename detail::function::function_return_type::type result_type; #endif // BOOST_NO_VOID_RETURNS ================ #圖16 function_base.hpp中的一個struct,用以決定「被指涉函式」的返回型別。其所附帶的註釋頗值一讀,一併附上。 =============/** * The unusable class is a placeholder for unused function arguments * It is also completely unusable except that it constructable from * anything. This helps compilers without partial specialization to * handle Boost.Function objects returning void. */ struct unusable { unusable() {} template unusable(const T&) {} }; /* Determine the return type. This supports compilers that do not support * void returns or partial specialization by silently changing the return * type to "unusable". */ template struct function_return_type { typedef T type; }; template<> struct function_return_type { typedef unusable type; }; ================ #圖17 預處理器完成工作後,獲得class function0。 ============= template< typename R , typename Allocator = int > class function0 : public function_base { public: typedef typename detail::function::function_return_type::type result_type; ... typedef result_type (*invoker_type)(detail::function::any_pointer); invoker_type invoker; }; ================ #圖18 預處理器完成工作後,獲得class function1。 ============= template< typename R , typename T0 , typename Allocator = int > class function1 : public function_base { public: typedef typename detail::function::function_return_type::type result_type; typedef T0 argument_type; ... typedef result_type (*invoker_type)(detail::function::any_pointer , T0); invoker_type invoker; }; ================ #圖19 預處理器完成工作後,獲得class function2。 ============= template< typename R , typename T0 , typename T1, typename Allocator = int > class function2 : public function_base { public: typedef typename detail::function::function_return_type::type result_type; typedef T0 first_argument_type; typedef T1 second_argument_type; ... typedef result_type (*invoker_type)(detail::function::any_pointer , T0,T1); invoker_type invoker; }; ================ #圖20 預處理器完成工作後,獲得class function10。 ============= template< typename R , typename T0 , typename T1 , typename T2 , typename T3 , typename T4 , typename T5 , typename T6 , typename T7 , typename T8 , typename T9, typename Allocator = int > class function10 : public function_base { typedef typename detail::function::function_return_type::type result_type; typedef T0 arg1_type; typedef T1 arg2_type; typedef T2 arg3_type; typedef T3 arg4_type; typedef T4 arg5_type; typedef T5 arg6_type; typedef T6 arg7_type; typedef T7 arg8_type; typedef T8 arg9_type; typedef T9 arg10_type; ... typedef result_type (*invoker_type)(detail::function::any_pointer , T0,T1,T2,T3,T4,T5,T6,T7,T8,T9); invoker_type invoker; }; ================ ===<反灰>============= function2 f2; f2 = &func2; cout << f2(10, 1.1) << endl; ================ ===<反灰>============= function2() : function_base(), invoker(0) {} ================ ===<反灰>============= typedef result_type (*invoker_type)(detail::function::any_pointer, T0,T1); invoker_type invoker; ================ ===<反灰>============= typedef bool (*invoker_type)(any_pointer, int, double); invoker_type invoker; ================ ===<反灰>============= union any_pointer { void* obj_ptr; const void* const_obj_ptr; void (*func_ptr)(); char data[1]; }; ================ #圖21 三個函式分別以三種不同的成分建立一個any_pointer。 ============= inline any_pointer make_any_pointer(void* o) { any_pointer p; p.obj_ptr = o; return p; } inline any_pointer make_any_pointer(const void* o) { any_pointer p; p.const_obj_ptr = o; return p; } inline any_pointer make_any_pointer(void (*f)()) { any_pointer p; p.func_ptr = f; return p; } ================ #圖22 function_base源碼摘錄(錄自function_base.hpp)。 ============= /* * 這個class內含function1, function2, function3...等classes * 所需的基本元素。它是所有functions的共同父類別 */ class function_base { public: function_base() : manager(0) { functor.obj_ptr = 0; } bool empty() const { return !manager; } public: detail::function::any_pointer (*manager)(detail::function::any_pointer, detail::function::functor_manager_operation_type); detail::function::any_pointer functor; ... } ================ #圖23 出現於圖22中的functor_manager_operation_type,其定義出自function_base.hpp。其內三個命名可想像分別是1,2,3。 ============= enum functor_manager_operation_type { clone_functor_tag, destroy_functor_tag, check_functor_type_tag }; ================ ===<反灰>============= function2 f2; f2 = &func2; cout << f2(10, 1.1) << endl; ================ ===<反灰>============= template function2& operator=(Functor const & f) { function2(f).swap(*this); //這裡非常繁複,不多說明 return *this; } ================ ===<反灰>============= function2 f2; f2 = &func2; cout << f2(10, 1.1) << endl; ================ ===<反灰>============= bool operator()(int a0, double a1) const { if (this->empty()) boost::throw_exception(bad_function_call()); return invoker(this->functor, a0, a1); } ================ ==作者簡介 =========== 侯捷 資訊顧問、專欄主筆、大學執教。常著文章自娛,頗示己志。 侯捷網站:http://www.jjhou.com(繁體) 北京鏡站:http://jjhou.csdn.net(簡體) 永久郵箱:jjhou@jjhou.com ================