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]
This commit is contained in:
Douglas Gregor
2002-01-30 04:33:45 +00:00
parent 39f6d34db8
commit 6882358627
2 changed files with 108 additions and 18 deletions

View File

@ -86,13 +86,17 @@ namespace boost {
* so function requires a union of the two. */ * so function requires a union of the two. */
union any_pointer union any_pointer
{ {
class incomplete;
void* obj_ptr; void* obj_ptr;
const void* const_obj_ptr; const void* const_obj_ptr;
void (*func_ptr)(); void (*func_ptr)();
void (incomplete::*mem_func_ptr)();
explicit any_pointer(void* p) : obj_ptr(p) {} explicit any_pointer(void* p) : obj_ptr(p) {}
explicit any_pointer(const void* p) : const_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 (*p)()) : func_ptr(p) {}
explicit any_pointer(void (incomplete::*p)()) : mem_func_ptr(p) {}
}; };
/** /**
@ -139,7 +143,7 @@ namespace boost {
function_ptr_tag, function_ptr_tag,
function_obj_tag>::type ptr_or_obj_tag; function_obj_tag>::type ptr_or_obj_tag;
typedef typename IF<(is_member_pointer<F>::value), typedef typename IF<(is_member_function_pointer<F>::value),
member_ptr_tag, member_ptr_tag,
ptr_or_obj_tag>::type ptr_or_obj_or_mem_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 // The trivial manager does nothing but return the same pointer (if we
// are cloning) or return the null pointer (if we are deleting). // are cloning) or return the null pointer (if we are deleting).
inline any_pointer trivial_manager(any_pointer f, inline any_pointer trivial_manager(any_pointer f,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
return f; return f;

View File

@ -45,7 +45,11 @@
#define BOOST_FUNCTION_FUNCTION_INVOKER \ #define BOOST_FUNCTION_FUNCTION_INVOKER \
BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ #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 \ #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \ #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
@ -56,6 +60,8 @@
BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) 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 \ #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
#define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \ #define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \
@ -88,7 +94,6 @@ namespace boost {
{ {
static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
f(BOOST_FUNCTION_ARGS); 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< template<
typename FunctionObj, typename FunctionObj,
typename R BOOST_FUNCTION_COMMA typename R BOOST_FUNCTION_COMMA
@ -182,6 +220,29 @@ namespace boost {
>::type type; >::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<R>::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< template<
typename FunctionObj, typename FunctionObj,
typename R BOOST_FUNCTION_COMMA typename R BOOST_FUNCTION_COMMA
@ -350,7 +411,9 @@ namespace boost {
void clear() void clear()
{ {
if (function_base::manager) 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; function_base::manager = 0;
invoker = 0; invoker = 0;
@ -362,7 +425,9 @@ namespace boost {
if (!f.empty()) { if (!f.empty()) {
invoker = f.invoker; invoker = f.invoker;
function_base::manager = f.manager; 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(); clear();
if (f) { if (f) {
typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< typedef typename detail::function::
FunctionPtr, BOOST_FUNCTION_GET_FUNCTION_INVOKER<
R BOOST_FUNCTION_COMMA FunctionPtr,
BOOST_FUNCTION_TEMPLATE_ARGS R BOOST_FUNCTION_COMMA
>::type BOOST_FUNCTION_TEMPLATE_ARGS
>::type
invoker_type; invoker_type;
invoker = &invoker_type::invoke; invoker = &invoker_type::invoke;
function_base::manager = &detail::function::functor_manager<FunctionPtr, function_base::manager = &detail::function::functor_manager<
Allocator>::manage; FunctionPtr, Allocator>::manage;
function_base::functor = function_base::manager(detail::function::any_pointer( function_base::functor =
function_base::manager(
detail::function::any_pointer(
// should be a reinterpret cast, but some compilers // should be a reinterpret cast, but some compilers
// insist on giving cv-qualifiers to free functions // insist on giving cv-qualifiers to free functions
(void (*)())(f) (void (*)())(f)),
), detail::function::clone_functor_tag);
detail::function::clone_functor_tag);
} }
} }
@ -402,7 +469,24 @@ namespace boost {
template<typename MemberPtr> template<typename MemberPtr>
void assign_to(MemberPtr f, detail::function::member_ptr_tag) 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 #endif // BOOST_FUNCTION_NUM_ARGS > 0
@ -501,6 +585,8 @@ namespace boost {
#undef BOOST_FUNCTION_INVOKER_BASE #undef BOOST_FUNCTION_INVOKER_BASE
#undef BOOST_FUNCTION_FUNCTION_INVOKER #undef BOOST_FUNCTION_FUNCTION_INVOKER
#undef BOOST_FUNCTION_VOID_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_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER