From 6882358627d4f11a0bf336ab7f35d29fcd9c3f1a Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 30 Jan 2002 04:33:45 +0000 Subject: [PATCH] function_base.hpp: function_template.hpp: - Add support for storing member function pointers directly within the Boost.Function object, without allocating any extra memory [SVN r12568] --- include/boost/function/function_base.hpp | 8 +- include/boost/function/function_template.hpp | 118 ++++++++++++++++--- 2 files changed, 108 insertions(+), 18 deletions(-) diff --git a/include/boost/function/function_base.hpp b/include/boost/function/function_base.hpp index 1542512..eba353c 100644 --- a/include/boost/function/function_base.hpp +++ b/include/boost/function/function_base.hpp @@ -86,13 +86,17 @@ namespace boost { * so function requires a union of the two. */ union any_pointer { + class incomplete; + void* obj_ptr; const void* const_obj_ptr; void (*func_ptr)(); + void (incomplete::*mem_func_ptr)(); explicit any_pointer(void* p) : obj_ptr(p) {} explicit any_pointer(const void* p) : const_obj_ptr(p) {} explicit any_pointer(void (*p)()) : func_ptr(p) {} + explicit any_pointer(void (incomplete::*p)()) : mem_func_ptr(p) {} }; /** @@ -139,7 +143,7 @@ namespace boost { function_ptr_tag, function_obj_tag>::type ptr_or_obj_tag; - typedef typename IF<(is_member_pointer::value), + typedef typename IF<(is_member_function_pointer::value), member_ptr_tag, ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag; @@ -156,7 +160,7 @@ namespace boost { // The trivial manager does nothing but return the same pointer (if we // are cloning) or return the null pointer (if we are deleting). inline any_pointer trivial_manager(any_pointer f, - functor_manager_operation_type op) + functor_manager_operation_type op) { if (op == clone_functor_tag) return f; diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index bc2d85f..f02d991 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -45,7 +45,11 @@ #define BOOST_FUNCTION_FUNCTION_INVOKER \ BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ - BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS) + BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_MEM_FUNCTION_INVOKER \ + BOOST_JOIN(member_function_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_MEM_VOID_FUNCTION_INVOKER \ + BOOST_JOIN(member_void_function_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \ BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \ @@ -56,6 +60,8 @@ BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER \ + BOOST_JOIN(get_member_function_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \ @@ -88,7 +94,6 @@ namespace boost { { static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) - { FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); f(BOOST_FUNCTION_ARGS); @@ -96,6 +101,39 @@ namespace boost { } }; +#if BOOST_FUNCTION_NUM_ARGS > 0 + template< + typename MemberPtr, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_MEM_FUNCTION_INVOKER + { + static R invoke(any_pointer member_ptr BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + { + MemberPtr f = (MemberPtr)(member_ptr.mem_func_ptr); + return mem_fn(f)(BOOST_FUNCTION_ARGS); + } + }; + + template< + typename MemberPtr, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_MEM_VOID_FUNCTION_INVOKER + { + static unusable invoke(any_pointer member_ptr BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + { + MemberPtr f = (MemberPtr)(member_ptr.mem_func_ptr); + mem_fn(f)(BOOST_FUNCTION_ARGS); + return unusable(); + } + }; +#endif + template< typename FunctionObj, typename R BOOST_FUNCTION_COMMA @@ -182,6 +220,29 @@ namespace boost { >::type type; }; +#if BOOST_FUNCTION_NUM_ARGS > 0 + template< + typename MemberPtr, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER + { + typedef typename IF<(is_void::value), + BOOST_FUNCTION_MEM_VOID_FUNCTION_INVOKER< + MemberPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >, + BOOST_FUNCTION_MEM_FUNCTION_INVOKER< + MemberPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + > + >::type type; + }; +#endif + template< typename FunctionObj, typename R BOOST_FUNCTION_COMMA @@ -350,7 +411,9 @@ namespace boost { void clear() { if (function_base::manager) - function_base::functor = function_base::manager(function_base::functor, detail::function::destroy_functor_tag); + function_base::functor = function_base::manager( + function_base::functor, + detail::function::destroy_functor_tag); function_base::manager = 0; invoker = 0; @@ -362,7 +425,9 @@ namespace boost { if (!f.empty()) { invoker = f.invoker; function_base::manager = f.manager; - function_base::functor = f.manager(f.functor, detail::function::clone_functor_tag); + function_base::functor = f.manager( + f.functor, + detail::function::clone_functor_tag); } } @@ -379,22 +444,24 @@ namespace boost { clear(); if (f) { - typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< - FunctionPtr, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - >::type + typedef typename detail::function:: + BOOST_FUNCTION_GET_FUNCTION_INVOKER< + FunctionPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type invoker_type; invoker = &invoker_type::invoke; - function_base::manager = &detail::function::functor_manager::manage; - function_base::functor = function_base::manager(detail::function::any_pointer( + function_base::manager = &detail::function::functor_manager< + FunctionPtr, Allocator>::manage; + function_base::functor = + function_base::manager( + detail::function::any_pointer( // should be a reinterpret cast, but some compilers // insist on giving cv-qualifiers to free functions - (void (*)())(f) - ), - detail::function::clone_functor_tag); + (void (*)())(f)), + detail::function::clone_functor_tag); } } @@ -402,7 +469,24 @@ namespace boost { template void assign_to(MemberPtr f, detail::function::member_ptr_tag) { - this->assign_to(mem_fn(f)); + clear(); + + if (f) { + typedef detail::function::any_pointer any_pointer; + + typedef typename detail::function:: + BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER< + MemberPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + invoker_type; + + invoker = &invoker_type::invoke; + function_base::manager = &detail::function::trivial_manager; + function_base::functor = + any_pointer((void (any_pointer::incomplete::*)())(f)); + } } #endif // BOOST_FUNCTION_NUM_ARGS > 0 @@ -501,6 +585,8 @@ namespace boost { #undef BOOST_FUNCTION_INVOKER_BASE #undef BOOST_FUNCTION_FUNCTION_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER +#undef BOOST_FUNCTION_MEM_FUNCTION_INVOKER +#undef BOOST_FUNCTION_MEM_VOID_FUNCTION_INVOKER #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER