function_base.hpp:

- has_empty_target modified to deal only with function objects, and to not
    require pointers to the function objects.

function_template.hpp:
  - Don't use '&' operation on incoming function objects


[SVN r13318]
This commit is contained in:
Douglas Gregor
2002-03-30 18:45:28 +00:00
parent 02f5d9d0e0
commit 28984e4f23
2 changed files with 69 additions and 109 deletions

View File

@ -34,6 +34,8 @@
namespace boost { namespace boost {
namespace detail { namespace detail {
namespace function { namespace function {
template<bool> struct truth {};
/* /*
* The IF implementation is temporary code. When a Boost metaprogramming * The IF implementation is temporary code. When a Boost metaprogramming
* library is introduced, Boost.Function will use it instead. * library is introduced, Boost.Function will use it instead.
@ -156,7 +158,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;
@ -176,7 +178,8 @@ namespace boost {
// For function pointers, the manager is trivial // For function pointers, the manager is trivial
static inline any_pointer static inline any_pointer
manager(any_pointer function_ptr, functor_manager_operation_type op, manager(any_pointer function_ptr,
functor_manager_operation_type op,
function_ptr_tag) function_ptr_tag)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
@ -333,92 +336,20 @@ namespace boost {
namespace detail { namespace detail {
namespace function { namespace function {
/** // The result is not a Boost.Function object, so we assume that this
* Determine if the given target is empty. // target is not empty
*/ template<typename FunctionObj>
inline bool has_empty_target(const FunctionObj&, truth<false>)
{
return false;
}
// Fallback - assume target is not empty // The result is a Boost.Function object, so query whether it is empty
inline bool has_empty_target(...) // or not
template<typename FunctionObj>
inline bool has_empty_target(const FunctionObj& f, truth<true>)
{ {
return false; return f.empty();
}
// If the target is a 'function', query the empty() method
inline bool has_empty_target(const function_base* af)
{
return af->empty();
}
// If the target is a 'function', query the empty() method
inline bool has_empty_target(const function_base& af)
{
return af.empty();
}
// A function pointer is empty if it is null
template<typename R>
inline bool has_empty_target(R (*f)())
{
return f == 0;
}
template<typename R, typename T1>
inline bool has_empty_target(R (*f)(T1))
{
return f == 0;
}
template<typename R, typename T1, typename T2>
inline bool has_empty_target(R (*f)(T1, T2))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3>
inline bool has_empty_target(R (*f)(T1, T2, T3))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7, T8))
{
return f == 0;
}
template<typename R, typename T1, typename T2, typename T3, typename T4,
typename T5, typename T6, typename T7, typename T8, typename T9>
inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9))
{
return f == 0;
} }
} // end namespace function } // end namespace function
} // end namespace detail } // end namespace detail
@ -430,14 +361,18 @@ namespace boost {
inline void postcall(const function_base*) {} inline void postcall(const function_base*) {}
}; };
// The default function mixin does nothing. The assignment and copy-construction operators // The default function mixin does nothing. The assignment and
// are all defined because MSVC defines broken versions. // copy-construction operators are all defined because MSVC defines broken
struct empty_function_mixin { // versions.
empty_function_mixin() {}; struct empty_function_mixin
empty_function_mixin(const empty_function_mixin&) {}; {
empty_function_mixin() {}
empty_function_mixin(const empty_function_mixin&) {}
empty_function_mixin& operator=(const empty_function_mixin&) empty_function_mixin& operator=(const empty_function_mixin&)
{return *this; } {
return *this;
}
}; };
} }

View File

@ -361,9 +361,12 @@ namespace boost {
// Clear out a target, if there is one // Clear out a target, if there is one
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;
} }
@ -374,7 +377,8 @@ 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);
} }
} }
@ -399,9 +403,10 @@ namespace boost {
invoker_type; invoker_type;
invoker = &invoker_type::invoke; invoker = &invoker_type::invoke;
function_base::manager = &detail::function::functor_manager<FunctionPtr, function_base::manager =
Allocator>::manage; &detail::function::functor_manager<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)
@ -421,7 +426,11 @@ namespace boost {
template<typename FunctionObj> template<typename FunctionObj>
void assign_to(FunctionObj f, detail::function::function_obj_tag) void assign_to(FunctionObj f, detail::function::function_obj_tag)
{ {
if (!detail::function::has_empty_target(&f)) { typedef detail::function::truth<
boost::is_base_and_derived<function_base, FunctionObj>::value>
is_boost_function;
if (!detail::function::has_empty_target(f, is_boost_function())) {
typedef typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj, FunctionObj,
@ -431,11 +440,23 @@ namespace boost {
invoker_type; invoker_type;
invoker = &invoker_type::invoke; invoker = &invoker_type::invoke;
function_base::manager = &detail::function::functor_manager<FunctionObj, function_base::manager = &detail::function::functor_manager<
Allocator>::manage; FunctionObj, Allocator>::manage;
#ifndef BOOST_NO_STD_ALLOCATOR
typedef typename Allocator::template rebind<FunctionObj>::other
allocator_type;
typedef typename allocator_type::pointer pointer_type;
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
function_base::functor = function_base::functor =
function_base::manager(detail::function::any_pointer(const_cast<FunctionObj*>(&f)), detail::function::any_pointer(static_cast<void*>(new_f));
detail::function::clone_functor_tag);
} }
} }
@ -443,7 +464,11 @@ namespace boost {
void assign_to(const reference_wrapper<FunctionObj>& f, void assign_to(const reference_wrapper<FunctionObj>& f,
detail::function::function_obj_ref_tag) detail::function::function_obj_ref_tag)
{ {
if (!detail::function::has_empty_target(&f.get())) { typedef detail::function::truth<
boost::is_base_and_derived<function_base, FunctionObj>::value>
is_boost_function;
if (!detail::function::has_empty_target(f.get(), is_boost_function())) {
typedef typedef
typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
FunctionObj, FunctionObj,
@ -455,9 +480,10 @@ namespace boost {
invoker = &invoker_type::invoke; invoker = &invoker_type::invoke;
function_base::manager = &detail::function::trivial_manager; function_base::manager = &detail::function::trivial_manager;
function_base::functor = function_base::functor =
function_base::manager(detail::function::any_pointer( function_base::manager(
const_cast<FunctionObj*>(&f.get())), detail::function::any_pointer(
detail::function::clone_functor_tag); const_cast<FunctionObj*>(f.get_pointer())),
detail::function::clone_functor_tag);
} }
} }
@ -521,4 +547,3 @@ namespace boost {
#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER