diff -U 3 -H -d -r -N -- boost_1_34_1/boost/function/function_base.hpp boost_1_34_1-patched/boost/function/function_base.hpp --- boost_1_34_1/boost/function/function_base.hpp 2006-10-13 16:29:45.000000000 +0200 +++ boost_1_34_1-patched/boost/function/function_base.hpp 2007-12-22 10:21:10.000000000 +0100 @@ -15,6 +15,7 @@ #include #include #include +#include // unary_function, binary_function #include #include #include @@ -30,6 +31,20 @@ #endif #include +#if defined(BOOST_MSVC) +# pragma warning( push ) +# pragma warning( disable : 4793 ) // complaint about native code generation +# pragma warning( disable : 4127 ) // "conditional expression is constant" +#endif + +// Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info. +#ifdef BOOST_NO_EXCEPTION_STD_NAMESPACE +// Embedded VC++ does not have type_info in namespace std +# define BOOST_FUNCTION_STD_NS +#else +# define BOOST_FUNCTION_STD_NS std +#endif + // Borrowed from Boost.Python library: determines the cases where we // need to use std::type_info::name to compare instead of operator==. # if (defined(__GNUC__) && __GNUC__ >= 3) \ @@ -59,7 +74,7 @@ #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \ - || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540) + || !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540) # define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX #endif @@ -198,8 +213,8 @@ struct reference_manager { static inline void - get(const function_buffer& in_buffer, function_buffer& out_buffer, - functor_manager_operation_type op) + manage(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op) { switch (op) { case clone_functor_tag: @@ -215,8 +230,8 @@ // DPG TBD: Since we're only storing a pointer, it's // possible that the user could ask for a base class or // derived class. Is that okay? - const std::type_info& check_type = - *static_cast(out_buffer.const_obj_ptr); + const BOOST_FUNCTION_STD_NS::type_info& check_type = + *static_cast(out_buffer.const_obj_ptr); if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F))) out_buffer.obj_ptr = in_buffer.obj_ptr; else @@ -265,8 +280,8 @@ else if (op == destroy_functor_tag) out_buffer.func_ptr = 0; else /* op == check_functor_type_tag */ { - const std::type_info& check_type = - *static_cast(out_buffer.const_obj_ptr); + const BOOST_FUNCTION_STD_NS::type_info& check_type = + *static_cast(out_buffer.const_obj_ptr); if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor))) out_buffer.obj_ptr = &in_buffer.func_ptr; else @@ -287,8 +302,8 @@ // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type. reinterpret_cast(&out_buffer.data)->~Functor(); } else /* op == check_functor_type_tag */ { - const std::type_info& check_type = - *static_cast(out_buffer.const_obj_ptr); + const BOOST_FUNCTION_STD_NS::type_info& check_type = + *static_cast(out_buffer.const_obj_ptr); if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor))) out_buffer.obj_ptr = &in_buffer.data; else @@ -348,8 +363,8 @@ # endif // BOOST_NO_STD_ALLOCATOR out_buffer.obj_ptr = 0; } else /* op == check_functor_type_tag */ { - const std::type_info& check_type = - *static_cast(out_buffer.const_obj_ptr); + const BOOST_FUNCTION_STD_NS::type_info& check_type = + *static_cast(out_buffer.const_obj_ptr); if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor))) out_buffer.obj_ptr = in_buffer.obj_ptr; else @@ -368,6 +383,15 @@ mpl::bool_<(function_allows_small_object_optimization::value)>()); } + // For member pointers, we treat them as function objects with + // the small-object optimization always enabled. + static inline void + manager(const function_buffer& in_buffer, function_buffer& out_buffer, + functor_manager_operation_type op, member_ptr_tag) + { + manager(in_buffer, out_buffer, op, mpl::true_()); + } + public: /* Dispatch to an appropriate manager based on whether we have a function pointer or a function object pointer. */ @@ -456,7 +480,6 @@ */ struct vtable_base { - vtable_base() : manager(0) { } void (*manager)(const function_buffer& in_buffer, function_buffer& out_buffer, functor_manager_operation_type op); @@ -480,13 +503,13 @@ /** Retrieve the type of the stored function object, or typeid(void) if this is empty. */ - const std::type_info& target_type() const + const BOOST_FUNCTION_STD_NS::type_info& target_type() const { if (!vtable) return typeid(void); detail::function::function_buffer type; vtable->manager(functor, type, detail::function::get_functor_type_tag); - return *static_cast(type.const_obj_ptr); + return *static_cast(type.const_obj_ptr); } template @@ -558,7 +581,7 @@ #endif public: // should be protected, but GCC 2.95.3 will fail to allow access - detail::function::vtable_base* vtable; + const detail::function::vtable_base* vtable; mutable detail::function::function_buffer functor; }; @@ -733,4 +756,8 @@ #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL #undef BOOST_FUNCTION_COMPARE_TYPE_ID +#if defined(BOOST_MSVC) +# pragma warning( pop ) +#endif + #endif // BOOST_FUNCTION_BASE_HEADER diff -U 3 -H -d -r -N -- boost_1_34_1/boost/function/function_template.hpp boost_1_34_1-patched/boost/function/function_template.hpp --- boost_1_34_1/boost/function/function_template.hpp 2006-09-29 19:23:28.000000000 +0200 +++ boost_1_34_1-patched/boost/function/function_template.hpp 2007-12-21 10:03:05.000000000 +0100 @@ -11,6 +11,11 @@ // protection. #include +#if defined(BOOST_MSVC) +# pragma warning( push ) +# pragma warning( disable : 4127 ) // "conditional expression is constant" +#endif + #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T) @@ -54,12 +59,20 @@ BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \ BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_MEMBER_INVOKER \ + BOOST_JOIN(member_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_VOID_MEMBER_INVOKER \ + BOOST_JOIN(void_member_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ BOOST_JOIN(get_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_FUNCTION_REF_INVOKER \ BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_GET_MEMBER_INVOKER \ + BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS) +#define BOOST_FUNCTION_GET_INVOKER \ + BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS) #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS) #ifndef BOOST_NO_VOID_RETURNS @@ -70,16 +83,6 @@ # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE () #endif -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4127) // conditional expression is constant. -#endif - -#ifdef BOOST_MSVC -# pragma warning(push) -# pragma warning(disable: 4127) // conditional expression is constant. -#endif - namespace boost { namespace detail { namespace function { @@ -191,6 +194,44 @@ } }; +#if BOOST_FUNCTION_NUM_ARGS > 0 + /* Handle invocation of member pointers. */ + template< + typename MemberPtr, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_MEMBER_INVOKER + { + static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + + { + MemberPtr* f = + reinterpret_cast(&function_obj_ptr.data); + return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS); + } + }; + + template< + typename MemberPtr, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_VOID_MEMBER_INVOKER + { + static BOOST_FUNCTION_VOID_RETURN_TYPE + invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA + BOOST_FUNCTION_PARMS) + + { + MemberPtr* f = + reinterpret_cast(&function_obj_ptr.data); + BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS)); + } + }; +#endif + template< typename FunctionPtr, typename R BOOST_FUNCTION_COMMA @@ -254,12 +295,130 @@ >::type type; }; +#if BOOST_FUNCTION_NUM_ARGS > 0 + /* Retrieve the appropriate invoker for a member pointer. */ + template< + typename MemberPtr, + typename R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_PARMS + > + struct BOOST_FUNCTION_GET_MEMBER_INVOKER + { + typedef typename mpl::if_c<(is_void::value), + BOOST_FUNCTION_VOID_MEMBER_INVOKER< + MemberPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >, + BOOST_FUNCTION_MEMBER_INVOKER< + MemberPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + > + >::type type; + }; +#endif + + /* Given the tag returned by get_function_tag, retrieve the + actual invoker that will be used for the given function + object. + + Each specialization contains an "apply" nested class template + that accepts the function object, return type, function + argument types, and allocator. The resulting "apply" class + contains two typedefs, "invoker_type" and "manager_type", + which correspond to the invoker and manager types. */ + template + struct BOOST_FUNCTION_GET_INVOKER { }; + + /* Retrieve the invoker for a function pointer. */ + template<> + struct BOOST_FUNCTION_GET_INVOKER + { + template + struct apply + { + typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< + FunctionPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + invoker_type; + + typedef functor_manager manager_type; + }; + }; + +#if BOOST_FUNCTION_NUM_ARGS > 0 + /* Retrieve the invoker for a member pointer. */ + template<> + struct BOOST_FUNCTION_GET_INVOKER + { + template + struct apply + { + typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER< + MemberPtr, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + invoker_type; + + typedef functor_manager manager_type; + }; + }; +#endif + + /* Retrieve the invoker for a function object. */ + template<> + struct BOOST_FUNCTION_GET_INVOKER + { + template + struct apply + { + typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< + FunctionObj, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + invoker_type; + + typedef functor_manager manager_type; + }; + }; + + /* Retrieve the invoker for a reference to a function object. */ + template<> + struct BOOST_FUNCTION_GET_INVOKER + { + template + struct apply + { + typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< + typename RefWrapper::type, + R BOOST_FUNCTION_COMMA + BOOST_FUNCTION_TEMPLATE_ARGS + >::type + invoker_type; + + typedef reference_manager manager_type; + }; + }; + /** * vtable for a specific boost::function instance. */ template - struct BOOST_FUNCTION_VTABLE : vtable_base + struct BOOST_FUNCTION_VTABLE { #ifndef BOOST_NO_VOID_RETURNS typedef R result_type; @@ -272,50 +431,25 @@ BOOST_FUNCTION_TEMPLATE_ARGS); template - BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0) - { - init(f); - } - - template - bool assign_to(F f, function_buffer& functor) + bool assign_to(const F& f, function_buffer& functor) const { typedef typename get_function_tag::type tag; return assign_to(f, functor, tag()); } - void clear(function_buffer& functor) + void clear(function_buffer& functor) const { - if (manager) - manager(functor, functor, destroy_functor_tag); + if (base.manager) + base.manager(functor, functor, destroy_functor_tag); } - +#ifndef BOOST_NO_PRIVATE_IN_AGGREGATE private: - template - void init(F f) - { - typedef typename get_function_tag::type tag; - init(f, tag()); - } - +#endif // Function pointers template - 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::manage; - } - - template bool - assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) + assign_to(FunctionPtr f, function_buffer& functor, + function_ptr_tag) const { this->clear(functor); if (f) { @@ -331,22 +465,13 @@ // Member pointers #if BOOST_FUNCTION_NUM_ARGS > 0 template - void init(MemberPtr f, member_ptr_tag) - { - // DPG TBD: Add explicit support for member function - // objects, so we invoke through mem_fn() but we retain the - // right target_type() values. - this->init(mem_fn(f)); - } - - template - bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) + bool + assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const { - // DPG TBD: Add explicit support for member function - // objects, so we invoke through mem_fn() but we retain the - // right target_type() values. if (f) { - this->assign_to(mem_fn(f), functor); + // Always use the small-object optimization for member + // pointers. + assign_functor(f, functor, mpl::true_()); return true; } else { return false; @@ -355,24 +480,11 @@ #endif // BOOST_FUNCTION_NUM_ARGS > 0 // Function objects - template - 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::manage; - } - // Assign to a function object using the small object optimization template void - assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) + assign_functor(const FunctionObj& f, function_buffer& functor, + mpl::true_) const { new ((void*)&functor.data) FunctionObj(f); } @@ -380,7 +492,8 @@ // Assign to a function object allocated on the heap. template void - assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) + assign_functor(const FunctionObj& f, function_buffer& functor, + mpl::false_) const { #ifndef BOOST_NO_STD_ALLOCATOR typedef typename Allocator::template rebind::other @@ -400,7 +513,8 @@ template bool - assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) + assign_to(const FunctionObj& f, function_buffer& functor, + function_obj_tag) const { if (!boost::detail::function::has_empty_target(boost::addressof(f))) { assign_functor(f, functor, @@ -413,24 +527,9 @@ // Reference to a function object template - void - init(const reference_wrapper& /*f*/, function_obj_ref_tag) - { - typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< - FunctionObj, - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - >::type - actual_invoker_type; - - invoker = &actual_invoker_type::invoke; - manager = &reference_manager::get; - } - - template bool assign_to(const reference_wrapper& f, - function_buffer& functor, function_obj_ref_tag) + function_buffer& functor, function_obj_ref_tag) const { if (!boost::detail::function::has_empty_target(f.get_pointer())) { // DPG TBD: We might need to detect constness of @@ -445,6 +544,7 @@ } public: + vtable_base base; invoker_type invoker; }; } // end namespace function @@ -456,6 +556,17 @@ typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR > class BOOST_FUNCTION_FUNCTION : public function_base + +#if BOOST_FUNCTION_NUM_ARGS == 1 + + , public std::unary_function + +#elif BOOST_FUNCTION_NUM_ARGS == 2 + + , public std::binary_function + +#endif + { public: #ifndef BOOST_NO_VOID_RETURNS @@ -537,7 +648,7 @@ if (this->empty()) boost::throw_exception(bad_function_call()); - return static_cast(vtable)->invoker + return reinterpret_cast(vtable)->invoker (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); } #else @@ -561,12 +672,16 @@ operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) { this->clear(); +#ifndef BOOST_NO_EXCEPTIONS try { this->assign_to(f); } catch (...) { vtable = 0; throw; } +#else + this->assign_to(f); +#endif return *this; } @@ -592,12 +707,16 @@ return *this; this->clear(); +#ifndef BOOST_NO_EXCEPTIONS try { this->assign_to_own(f); } catch (...) { vtable = 0; throw; } +#else + this->assign_to_own(f); +#endif return *this; } @@ -615,7 +734,7 @@ void clear() { if (vtable) { - static_cast(vtable)->clear(this->functor); + reinterpret_cast(vtable)->clear(this->functor); vtable = 0; } } @@ -650,10 +769,24 @@ } template - void assign_to(Functor f) + void assign_to(const Functor& f) { - static vtable_type stored_vtable(f); - if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable; + using detail::function::vtable_base; + + typedef typename detail::function::get_function_tag::type tag; + typedef detail::function::BOOST_FUNCTION_GET_INVOKER get_invoker; + typedef typename get_invoker:: + template apply + handler_type; + + typedef typename handler_type::invoker_type invoker_type; + typedef typename handler_type::manager_type manager_type; + + static const vtable_type stored_vtable = + { { &manager_type::manage }, &invoker_type::invoke }; + + if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable.base; else vtable = 0; } }; @@ -688,7 +821,7 @@ if (this->empty()) boost::throw_exception(bad_function_call()); - return static_cast(vtable)->invoker + return reinterpret_cast(vtable)->invoker (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); } #endif @@ -798,21 +931,14 @@ } }; -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif - #undef BOOST_FUNCTION_PARTIAL_SPEC #endif // have partial specialization } // end namespace boost -#ifdef BOOST_MSVC -# pragma warning(pop) -#endif - // Cleanup after ourselves... #undef BOOST_FUNCTION_VTABLE +#undef BOOST_FUNCTION_GET_INVOKER #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR #undef BOOST_FUNCTION_COMMA #undef BOOST_FUNCTION_FUNCTION @@ -822,10 +948,12 @@ #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER +#undef BOOST_FUNCTION_MEMBER_INVOKER +#undef BOOST_FUNCTION_VOID_MEMBER_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER -#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER +#undef BOOST_FUNCTION_GET_MEMBER_INVOKER #undef BOOST_FUNCTION_TEMPLATE_PARMS #undef BOOST_FUNCTION_TEMPLATE_ARGS #undef BOOST_FUNCTION_PARMS @@ -835,3 +963,7 @@ #undef BOOST_FUNCTION_ARG_TYPES #undef BOOST_FUNCTION_VOID_RETURN_TYPE #undef BOOST_FUNCTION_RETURN + +#if defined(BOOST_MSVC) +# pragma warning( pop ) +#endif