From 28984e4f23345744746db7ba9f9f4c7fe4d9d358 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Sat, 30 Mar 2002 18:45:28 +0000 Subject: [PATCH] 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] --- include/boost/function/function_base.hpp | 119 +++++-------------- include/boost/function/function_template.hpp | 59 ++++++--- 2 files changed, 69 insertions(+), 109 deletions(-) diff --git a/include/boost/function/function_base.hpp b/include/boost/function/function_base.hpp index 1542512..a4ea4bf 100644 --- a/include/boost/function/function_base.hpp +++ b/include/boost/function/function_base.hpp @@ -34,6 +34,8 @@ namespace boost { namespace detail { namespace function { + template struct truth {}; + /* * The IF implementation is temporary code. When a Boost metaprogramming * 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 // 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; @@ -176,7 +178,8 @@ namespace boost { // For function pointers, the manager is trivial 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) { if (op == clone_functor_tag) @@ -333,92 +336,20 @@ namespace boost { namespace detail { namespace function { - /** - * Determine if the given target is empty. - */ + // The result is not a Boost.Function object, so we assume that this + // target is not empty + template + inline bool has_empty_target(const FunctionObj&, truth) + { + return false; + } - // Fallback - assume target is not empty - inline bool has_empty_target(...) + // The result is a Boost.Function object, so query whether it is empty + // or not + template + inline bool has_empty_target(const FunctionObj& f, truth) { - return false; - } - - // 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 - inline bool has_empty_target(R (*f)()) - { - return f == 0; - } - - template - inline bool has_empty_target(R (*f)(T1)) - { - return f == 0; - } - - template - inline bool has_empty_target(R (*f)(T1, T2)) - { - return f == 0; - } - - template - inline bool has_empty_target(R (*f)(T1, T2, T3)) - { - return f == 0; - } - - template - inline bool has_empty_target(R (*f)(T1, T2, T3, T4)) - { - return f == 0; - } - - template - inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5)) - { - return f == 0; - } - - template - inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6)) - { - return f == 0; - } - - template - inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7)) - { - return f == 0; - } - - template - inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7, T8)) - { - return f == 0; - } - - template - inline bool has_empty_target(R (*f)(T1, T2, T3, T4, T5, T6, T7, T8, T9)) - { - return f == 0; + return f.empty(); } } // end namespace function } // end namespace detail @@ -430,14 +361,18 @@ namespace boost { inline void postcall(const function_base*) {} }; - // The default function mixin does nothing. The assignment and copy-construction operators - // are all defined because MSVC defines broken versions. - struct empty_function_mixin { - empty_function_mixin() {}; - empty_function_mixin(const empty_function_mixin&) {}; + // The default function mixin does nothing. The assignment and + // copy-construction operators are all defined because MSVC defines broken + // versions. + struct empty_function_mixin + { + empty_function_mixin() {} + empty_function_mixin(const empty_function_mixin&) {} empty_function_mixin& operator=(const empty_function_mixin&) - {return *this; } + { + return *this; + } }; } diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index fce2a94..6055eeb 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -361,9 +361,12 @@ namespace boost { // Clear out a target, if there is one void clear() { - if (function_base::manager) - function_base::functor = function_base::manager(function_base::functor, detail::function::destroy_functor_tag); - + if (function_base::manager) { + function_base::functor = + function_base::manager(function_base::functor, + detail::function::destroy_functor_tag); + } + function_base::manager = 0; invoker = 0; } @@ -374,7 +377,8 @@ 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); } } @@ -399,9 +403,10 @@ namespace boost { 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::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) @@ -421,7 +426,11 @@ namespace boost { template 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::value> + is_boost_function; + + if (!detail::function::has_empty_target(f, is_boost_function())) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< FunctionObj, @@ -431,11 +440,23 @@ namespace boost { invoker_type; invoker = &invoker_type::invoke; - function_base::manager = &detail::function::functor_manager::manage; + function_base::manager = &detail::function::functor_manager< + FunctionObj, Allocator>::manage; +#ifndef BOOST_NO_STD_ALLOCATOR + typedef typename Allocator::template rebind::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(copy); +#else + FunctionObj* new_f = new FunctionObj(f); +#endif // BOOST_NO_STD_ALLOCATOR function_base::functor = - function_base::manager(detail::function::any_pointer(const_cast(&f)), - detail::function::clone_functor_tag); + detail::function::any_pointer(static_cast(new_f)); } } @@ -443,7 +464,11 @@ namespace boost { void assign_to(const reference_wrapper& f, detail::function::function_obj_ref_tag) { - if (!detail::function::has_empty_target(&f.get())) { + typedef detail::function::truth< + boost::is_base_and_derived::value> + is_boost_function; + + if (!detail::function::has_empty_target(f.get(), is_boost_function())) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< FunctionObj, @@ -455,9 +480,10 @@ namespace boost { invoker = &invoker_type::invoke; function_base::manager = &detail::function::trivial_manager; function_base::functor = - function_base::manager(detail::function::any_pointer( - const_cast(&f.get())), - detail::function::clone_functor_tag); + function_base::manager( + detail::function::any_pointer( + const_cast(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_STATELESS_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER -