$OpenBSD: patch-boost_function_function_template_hpp,v 1.1 2008/04/03 07:44:40 bernd Exp $ --- boost/function/function_template.hpp.orig Wed Jan 9 06:44:37 2008 +++ boost/function/function_template.hpp Wed Jan 9 06:45:08 2008 @@ -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,7 +194,45 @@ namespace boost { } }; +#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 BOOST_FUNCTION_TEMPLATE_PARMS @@ -254,12 +295,130 @@ namespace boost { >::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 @@ namespace boost { BOOST_FUNCTION_TEMPLATE_ARGS); template - BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0) + bool assign_to(const F& f, function_buffer& functor) const { - init(f); - } - - template - bool assign_to(F f, function_buffer& functor) - { 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 @@ namespace boost { // Member pointers #if BOOST_FUNCTION_NUM_ARGS > 0 template - void init(MemberPtr f, 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. - this->init(mem_fn(f)); - } - - template - bool assign_to(MemberPtr f, function_buffer& functor, 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. 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 @@ namespace boost { #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 @@ namespace boost { // 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 @@ namespace boost { 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 @@ namespace boost { // 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 @@ namespace boost { } public: + vtable_base base; invoker_type invoker; }; } // end namespace function @@ -456,6 +556,17 @@ namespace boost { 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 @@ namespace boost { 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 @@ namespace boost { 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 @@ namespace boost { 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 @@ namespace boost { void clear() { if (vtable) { - static_cast(vtable)->clear(this->functor); + reinterpret_cast(vtable)->clear(this->functor); vtable = 0; } } @@ -650,10 +769,24 @@ namespace boost { } 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 @@ namespace boost { 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 @@ class function } }; -#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 @@ class function #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 @@ class function #undef BOOST_FUNCTION_ARG_TYPES #undef BOOST_FUNCTION_VOID_RETURN_TYPE #undef BOOST_FUNCTION_RETURN + +#if defined(BOOST_MSVC) +# pragma warning( pop ) +#endif