forked from boostorg/function
function_base.hpp, function_template.hpp:
- Use a vtable instead of separate manager/invoker pointers, to shrink the size of a boost::function object to 8 bytes - Fix a problem with NULL member pointers [SVN r32186]
This commit is contained in:
@ -386,6 +386,16 @@ namespace boost {
|
|||||||
else return true;
|
else return true;
|
||||||
}
|
}
|
||||||
#endif // BOOST_NO_SFINAE
|
#endif // BOOST_NO_SFINAE
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the "manager" portion of the vtable for a
|
||||||
|
* boost::function object.
|
||||||
|
*/
|
||||||
|
struct vtable_base
|
||||||
|
{
|
||||||
|
vtable_base() : manager(0) { }
|
||||||
|
any_pointer (*manager)(any_pointer, functor_manager_operation_type);
|
||||||
|
};
|
||||||
} // end namespace function
|
} // end namespace function
|
||||||
} // end namespace detail
|
} // end namespace detail
|
||||||
|
|
||||||
@ -398,21 +408,21 @@ namespace boost {
|
|||||||
class function_base
|
class function_base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
function_base() : manager(0)
|
function_base() : vtable(0)
|
||||||
{
|
{
|
||||||
functor.obj_ptr = 0;
|
functor.obj_ptr = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is this function empty?
|
// Is this function empty?
|
||||||
bool empty() const { return !manager; }
|
bool empty() const { return !vtable; }
|
||||||
|
|
||||||
template<typename Functor>
|
template<typename Functor>
|
||||||
Functor* target()
|
Functor* target()
|
||||||
{
|
{
|
||||||
if (!manager) return 0;
|
if (!vtable) return 0;
|
||||||
|
|
||||||
detail::function::any_pointer result =
|
detail::function::any_pointer result =
|
||||||
manager(detail::function::make_any_pointer(&typeid(Functor)),
|
vtable->manager(detail::function::make_any_pointer(&typeid(Functor)),
|
||||||
detail::function::check_functor_type_tag);
|
detail::function::check_functor_type_tag);
|
||||||
if (!result.obj_ptr) return 0;
|
if (!result.obj_ptr) return 0;
|
||||||
else {
|
else {
|
||||||
@ -422,17 +432,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Functor>
|
template<typename Functor>
|
||||||
|
|
||||||
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||||
const Functor* target( Functor * = 0 ) const
|
const Functor* target( Functor * = 0 ) const
|
||||||
#else
|
#else
|
||||||
const Functor* target() const
|
const Functor* target() const
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
if (!manager) return 0;
|
if (!vtable) return 0;
|
||||||
|
|
||||||
detail::function::any_pointer result =
|
detail::function::any_pointer result =
|
||||||
manager(detail::function::make_any_pointer(&typeid(Functor)),
|
vtable->manager(detail::function::make_any_pointer(&typeid(Functor)),
|
||||||
detail::function::check_functor_type_tag);
|
detail::function::check_functor_type_tag);
|
||||||
if (!result.obj_ptr) return 0;
|
if (!result.obj_ptr) return 0;
|
||||||
else {
|
else {
|
||||||
@ -450,10 +459,11 @@ public:
|
|||||||
bool contains(const F& f) const
|
bool contains(const F& f) const
|
||||||
{
|
{
|
||||||
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
|
||||||
if (const F* fp = this->target( (F*)0 )) {
|
if (const F* fp = this->target( (F*)0 ))
|
||||||
#else
|
#else
|
||||||
if (const F* fp = this->template target<F>()) {
|
if (const F* fp = this->template target<F>())
|
||||||
#endif
|
#endif
|
||||||
|
{
|
||||||
return function_equal(*fp, f);
|
return function_equal(*fp, f);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -484,9 +494,7 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
public: // should be protected, but GCC 2.95.3 will fail to allow access
|
public: // should be protected, but GCC 2.95.3 will fail to allow access
|
||||||
detail::function::any_pointer (*manager)(
|
detail::function::vtable_base* vtable;
|
||||||
detail::function::any_pointer,
|
|
||||||
detail::function::functor_manager_operation_type);
|
|
||||||
detail::function::any_pointer functor;
|
detail::function::any_pointer functor;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -60,6 +60,7 @@
|
|||||||
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 \
|
||||||
BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
|
BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
|
||||||
|
#define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
|
||||||
|
|
||||||
#ifndef BOOST_NO_VOID_RETURNS
|
#ifndef BOOST_NO_VOID_RETURNS
|
||||||
# define BOOST_FUNCTION_VOID_RETURN_TYPE void
|
# define BOOST_FUNCTION_VOID_RETURN_TYPE void
|
||||||
@ -230,6 +231,201 @@ namespace boost {
|
|||||||
>::type type;
|
>::type type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* vtable for a specific boost::function instance.
|
||||||
|
*/
|
||||||
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
|
||||||
|
typename Allocator>
|
||||||
|
struct BOOST_FUNCTION_VTABLE : vtable_base
|
||||||
|
{
|
||||||
|
#ifndef BOOST_NO_VOID_RETURNS
|
||||||
|
typedef R result_type;
|
||||||
|
#else
|
||||||
|
typedef typename function_return_type<R>::type result_type;
|
||||||
|
#endif // BOOST_NO_VOID_RETURNS
|
||||||
|
|
||||||
|
typedef result_type (*invoker_type)(any_pointer
|
||||||
|
BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS);
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0)
|
||||||
|
{
|
||||||
|
init(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename F>
|
||||||
|
bool assign_to(F f, any_pointer& functor)
|
||||||
|
{
|
||||||
|
typedef typename get_function_tag<F>::type tag;
|
||||||
|
return assign_to(f, functor, tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear(any_pointer& functor)
|
||||||
|
{
|
||||||
|
if (manager)
|
||||||
|
functor = manager(functor, destroy_functor_tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<typename F>
|
||||||
|
void init(F f)
|
||||||
|
{
|
||||||
|
typedef typename get_function_tag<F>::type tag;
|
||||||
|
init(f, tag());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function pointers
|
||||||
|
template<typename FunctionPtr>
|
||||||
|
void init(FunctionPtr f, function_ptr_tag)
|
||||||
|
{
|
||||||
|
typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
|
||||||
|
FunctionPtr,
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS
|
||||||
|
>::type
|
||||||
|
actual_invoker_type;
|
||||||
|
|
||||||
|
invoker = &actual_invoker_type::invoke;
|
||||||
|
manager = &functor_manager<FunctionPtr, Allocator>::manage;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FunctionPtr>
|
||||||
|
bool assign_to(FunctionPtr f, any_pointer& functor, function_ptr_tag)
|
||||||
|
{
|
||||||
|
this->clear(functor);
|
||||||
|
if (f) {
|
||||||
|
// should be a reinterpret cast, but some compilers insist
|
||||||
|
// on giving cv-qualifiers to free functions
|
||||||
|
functor = manager(make_any_pointer((void (*)())(f)),
|
||||||
|
clone_functor_tag);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Member pointers
|
||||||
|
#if BOOST_FUNCTION_NUM_ARGS > 0
|
||||||
|
template<typename MemberPtr>
|
||||||
|
void init(MemberPtr f, member_ptr_tag)
|
||||||
|
{
|
||||||
|
this->init(mem_fn(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename MemberPtr>
|
||||||
|
bool assign_to(MemberPtr f, any_pointer& functor, member_ptr_tag)
|
||||||
|
{
|
||||||
|
if (f) {
|
||||||
|
this->assign_to(mem_fn(f), functor);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // BOOST_FUNCTION_NUM_ARGS > 0
|
||||||
|
|
||||||
|
// Stateful function objects
|
||||||
|
template<typename FunctionObj>
|
||||||
|
void init(FunctionObj f, function_obj_tag)
|
||||||
|
{
|
||||||
|
typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
|
||||||
|
FunctionObj,
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS
|
||||||
|
>::type
|
||||||
|
actual_invoker_type;
|
||||||
|
|
||||||
|
invoker = &actual_invoker_type::invoke;
|
||||||
|
manager = &functor_manager<FunctionObj, Allocator>::manage;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FunctionObj>
|
||||||
|
bool assign_to(FunctionObj f, any_pointer& functor, function_obj_tag)
|
||||||
|
{
|
||||||
|
if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
|
||||||
|
#ifndef BOOST_NO_STD_ALLOCATOR
|
||||||
|
typedef typename Allocator::template rebind<FunctionObj>::other
|
||||||
|
rebound_allocator_type;
|
||||||
|
typedef typename rebound_allocator_type::pointer pointer_type;
|
||||||
|
rebound_allocator_type allocator;
|
||||||
|
pointer_type copy = allocator.allocate(1);
|
||||||
|
allocator.construct(copy, f);
|
||||||
|
|
||||||
|
// Get back to the original pointer type
|
||||||
|
FunctionObj* new_f = static_cast<FunctionObj*>(copy);
|
||||||
|
#else
|
||||||
|
FunctionObj* new_f = new FunctionObj(f);
|
||||||
|
#endif // BOOST_NO_STD_ALLOCATOR
|
||||||
|
functor = make_any_pointer(static_cast<void*>(new_f));
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reference to a function object
|
||||||
|
template<typename FunctionObj>
|
||||||
|
void
|
||||||
|
init(const reference_wrapper<FunctionObj>& f, function_obj_ref_tag)
|
||||||
|
{
|
||||||
|
typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
|
||||||
|
FunctionObj,
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS
|
||||||
|
>::type
|
||||||
|
actual_invoker_type;
|
||||||
|
|
||||||
|
invoker = &actual_invoker_type::invoke;
|
||||||
|
manager = &trivial_manager<FunctionObj>::get;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FunctionObj>
|
||||||
|
bool
|
||||||
|
assign_to(const reference_wrapper<FunctionObj>& f, any_pointer& functor,
|
||||||
|
function_obj_ref_tag)
|
||||||
|
{
|
||||||
|
if (!boost::detail::function::has_empty_target(f.get_pointer())) {
|
||||||
|
functor = manager(make_any_pointer(
|
||||||
|
const_cast<FunctionObj*>(f.get_pointer())),
|
||||||
|
clone_functor_tag);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stateless function object
|
||||||
|
template<typename FunctionObj>
|
||||||
|
void
|
||||||
|
init(FunctionObj, stateless_function_obj_tag)
|
||||||
|
{
|
||||||
|
typedef
|
||||||
|
typename BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
|
||||||
|
FunctionObj,
|
||||||
|
R BOOST_FUNCTION_COMMA
|
||||||
|
BOOST_FUNCTION_TEMPLATE_ARGS
|
||||||
|
>::type actual_invoker_type;
|
||||||
|
invoker = &actual_invoker_type::invoke;
|
||||||
|
manager = &trivial_manager<FunctionObj>::get;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename FunctionObj>
|
||||||
|
bool
|
||||||
|
assign_to(FunctionObj f, any_pointer& functor,
|
||||||
|
stateless_function_obj_tag)
|
||||||
|
{
|
||||||
|
if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
|
||||||
|
functor = make_any_pointer(this);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
invoker_type invoker;
|
||||||
|
};
|
||||||
} // end namespace function
|
} // end namespace function
|
||||||
} // end namespace detail
|
} // end namespace detail
|
||||||
|
|
||||||
@ -249,6 +445,10 @@ namespace boost {
|
|||||||
#endif // BOOST_NO_VOID_RETURNS
|
#endif // BOOST_NO_VOID_RETURNS
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
|
||||||
|
R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Allocator>
|
||||||
|
vtable_type;
|
||||||
|
|
||||||
struct clear_type {};
|
struct clear_type {};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -274,8 +474,7 @@ namespace boost {
|
|||||||
typedef Allocator allocator_type;
|
typedef Allocator allocator_type;
|
||||||
typedef BOOST_FUNCTION_FUNCTION self_type;
|
typedef BOOST_FUNCTION_FUNCTION self_type;
|
||||||
|
|
||||||
BOOST_FUNCTION_FUNCTION() : function_base()
|
BOOST_FUNCTION_FUNCTION() : function_base() { }
|
||||||
, invoker(0) {}
|
|
||||||
|
|
||||||
// MSVC chokes if the following two constructors are collapsed into
|
// MSVC chokes if the following two constructors are collapsed into
|
||||||
// one with a default parameter.
|
// one with a default parameter.
|
||||||
@ -288,24 +487,21 @@ namespace boost {
|
|||||||
int>::type = 0
|
int>::type = 0
|
||||||
#endif // BOOST_NO_SFINAE
|
#endif // BOOST_NO_SFINAE
|
||||||
) :
|
) :
|
||||||
function_base(),
|
function_base()
|
||||||
invoker(0)
|
|
||||||
{
|
{
|
||||||
this->assign_to(f);
|
this->assign_to(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef BOOST_NO_SFINAE
|
#ifndef BOOST_NO_SFINAE
|
||||||
BOOST_FUNCTION_FUNCTION(clear_type*) : function_base(), invoker(0) {}
|
BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
|
||||||
#else
|
#else
|
||||||
BOOST_FUNCTION_FUNCTION(int zero) : function_base(), invoker(0)
|
BOOST_FUNCTION_FUNCTION(int zero) : function_base()
|
||||||
{
|
{
|
||||||
BOOST_ASSERT(zero == 0);
|
BOOST_ASSERT(zero == 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
|
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
|
||||||
function_base(),
|
|
||||||
invoker(0)
|
|
||||||
{
|
{
|
||||||
this->assign_to_own(f);
|
this->assign_to_own(f);
|
||||||
}
|
}
|
||||||
@ -320,7 +516,8 @@ namespace boost {
|
|||||||
if (this->empty())
|
if (this->empty())
|
||||||
boost::throw_exception(bad_function_call());
|
boost::throw_exception(bad_function_call());
|
||||||
|
|
||||||
return invoker(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
|
return static_cast<vtable_type*>(vtable)->invoker
|
||||||
|
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
result_type operator()(BOOST_FUNCTION_PARMS) const;
|
result_type operator()(BOOST_FUNCTION_PARMS) const;
|
||||||
@ -376,22 +573,17 @@ namespace boost {
|
|||||||
if (&other == this)
|
if (&other == this)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::swap(this->manager, other.manager);
|
|
||||||
std::swap(this->functor, other.functor);
|
std::swap(this->functor, other.functor);
|
||||||
std::swap(invoker, other.invoker);
|
std::swap(this->vtable, other.vtable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear out a target, if there is one
|
// Clear out a target, if there is one
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
if (this->manager) {
|
if (vtable) {
|
||||||
function_base::functor =
|
static_cast<vtable_type*>(vtable)->clear(this->functor);
|
||||||
this->manager(this->functor,
|
vtable = 0;
|
||||||
boost::detail::function::destroy_functor_tag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->manager = 0;
|
|
||||||
invoker = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
|
#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
|
||||||
@ -417,131 +609,20 @@ namespace boost {
|
|||||||
void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
|
void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
|
||||||
{
|
{
|
||||||
if (!f.empty()) {
|
if (!f.empty()) {
|
||||||
invoker = f.invoker;
|
this->vtable = f.vtable;
|
||||||
this->manager = f.manager;
|
|
||||||
this->functor =
|
this->functor =
|
||||||
f.manager(f.functor, boost::detail::function::clone_functor_tag);
|
f.vtable->manager(f.functor,
|
||||||
|
boost::detail::function::clone_functor_tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Functor>
|
template<typename Functor>
|
||||||
void assign_to(Functor f)
|
void assign_to(Functor f)
|
||||||
{
|
{
|
||||||
typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
|
static vtable_type stored_vtable(f);
|
||||||
this->assign_to(f, tag());
|
if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
|
||||||
|
else vtable = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename FunctionPtr>
|
|
||||||
void assign_to(FunctionPtr f, boost::detail::function::function_ptr_tag)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
|
|
||||||
if (f) {
|
|
||||||
typedef typename boost::detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
|
|
||||||
FunctionPtr,
|
|
||||||
R BOOST_FUNCTION_COMMA
|
|
||||||
BOOST_FUNCTION_TEMPLATE_ARGS
|
|
||||||
>::type
|
|
||||||
actual_invoker_type;
|
|
||||||
|
|
||||||
invoker = &actual_invoker_type::invoke;
|
|
||||||
this->manager =
|
|
||||||
&boost::detail::function::functor_manager<FunctionPtr, Allocator>::manage;
|
|
||||||
this->functor =
|
|
||||||
this->manager(boost::detail::function::make_any_pointer(
|
|
||||||
// should be a reinterpret cast, but some compilers
|
|
||||||
// insist on giving cv-qualifiers to free functions
|
|
||||||
(void (*)())(f)
|
|
||||||
),
|
|
||||||
boost::detail::function::clone_functor_tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if BOOST_FUNCTION_NUM_ARGS > 0
|
|
||||||
template<typename MemberPtr>
|
|
||||||
void assign_to(MemberPtr f, boost::detail::function::member_ptr_tag)
|
|
||||||
{
|
|
||||||
this->assign_to(mem_fn(f));
|
|
||||||
}
|
|
||||||
#endif // BOOST_FUNCTION_NUM_ARGS > 0
|
|
||||||
|
|
||||||
template<typename FunctionObj>
|
|
||||||
void assign_to(FunctionObj f, boost::detail::function::function_obj_tag)
|
|
||||||
{
|
|
||||||
if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
|
|
||||||
typedef
|
|
||||||
typename boost::detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
|
|
||||||
FunctionObj,
|
|
||||||
R BOOST_FUNCTION_COMMA
|
|
||||||
BOOST_FUNCTION_TEMPLATE_ARGS
|
|
||||||
>::type
|
|
||||||
actual_invoker_type;
|
|
||||||
|
|
||||||
invoker = &actual_invoker_type::invoke;
|
|
||||||
this->manager = &boost::detail::function::functor_manager<
|
|
||||||
FunctionObj, Allocator>::manage;
|
|
||||||
#ifndef BOOST_NO_STD_ALLOCATOR
|
|
||||||
typedef typename Allocator::template rebind<FunctionObj>::other
|
|
||||||
rebound_allocator_type;
|
|
||||||
typedef typename rebound_allocator_type::pointer pointer_type;
|
|
||||||
rebound_allocator_type allocator;
|
|
||||||
pointer_type copy = allocator.allocate(1);
|
|
||||||
allocator.construct(copy, f);
|
|
||||||
|
|
||||||
// Get back to the original pointer type
|
|
||||||
FunctionObj* new_f = static_cast<FunctionObj*>(copy);
|
|
||||||
#else
|
|
||||||
FunctionObj* new_f = new FunctionObj(f);
|
|
||||||
#endif // BOOST_NO_STD_ALLOCATOR
|
|
||||||
this->functor =
|
|
||||||
boost::detail::function::make_any_pointer(static_cast<void*>(new_f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename FunctionObj>
|
|
||||||
void assign_to(const reference_wrapper<FunctionObj>& f,
|
|
||||||
boost::detail::function::function_obj_ref_tag)
|
|
||||||
{
|
|
||||||
if (!boost::detail::function::has_empty_target(f.get_pointer())) {
|
|
||||||
typedef
|
|
||||||
typename boost::detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
|
|
||||||
FunctionObj,
|
|
||||||
R BOOST_FUNCTION_COMMA
|
|
||||||
BOOST_FUNCTION_TEMPLATE_ARGS
|
|
||||||
>::type
|
|
||||||
actual_invoker_type;
|
|
||||||
|
|
||||||
invoker = &actual_invoker_type::invoke;
|
|
||||||
this->manager = &boost::detail::function::trivial_manager<FunctionObj>::get;
|
|
||||||
this->functor =
|
|
||||||
this->manager(
|
|
||||||
boost::detail::function::make_any_pointer(
|
|
||||||
const_cast<FunctionObj*>(f.get_pointer())),
|
|
||||||
boost::detail::function::clone_functor_tag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename FunctionObj>
|
|
||||||
void assign_to(FunctionObj, boost::detail::function::stateless_function_obj_tag)
|
|
||||||
{
|
|
||||||
typedef
|
|
||||||
typename boost::detail::function::
|
|
||||||
BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
|
|
||||||
FunctionObj,
|
|
||||||
R BOOST_FUNCTION_COMMA
|
|
||||||
BOOST_FUNCTION_TEMPLATE_ARGS
|
|
||||||
>::type
|
|
||||||
actual_invoker_type;
|
|
||||||
invoker = &actual_invoker_type::invoke;
|
|
||||||
this->manager = &boost::detail::function::trivial_manager<FunctionObj>::get;
|
|
||||||
this->functor = boost::detail::function::make_any_pointer(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedef result_type (*invoker_type)(boost::detail::function::any_pointer
|
|
||||||
BOOST_FUNCTION_COMMA
|
|
||||||
BOOST_FUNCTION_TEMPLATE_ARGS);
|
|
||||||
|
|
||||||
invoker_type invoker;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
|
||||||
@ -574,7 +655,8 @@ namespace boost {
|
|||||||
if (this->empty())
|
if (this->empty())
|
||||||
boost::throw_exception(bad_function_call());
|
boost::throw_exception(bad_function_call());
|
||||||
|
|
||||||
return invoker(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
|
return static_cast<vtable_type*>(vtable)->invoker
|
||||||
|
(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -689,6 +771,7 @@ public:
|
|||||||
} // end namespace boost
|
} // end namespace boost
|
||||||
|
|
||||||
// Cleanup after ourselves...
|
// Cleanup after ourselves...
|
||||||
|
#undef BOOST_FUNCTION_VTABLE
|
||||||
#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
|
#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
|
||||||
#undef BOOST_FUNCTION_COMMA
|
#undef BOOST_FUNCTION_COMMA
|
||||||
#undef BOOST_FUNCTION_FUNCTION
|
#undef BOOST_FUNCTION_FUNCTION
|
||||||
|
Reference in New Issue
Block a user