// Boost.Function library // Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu) // // Permission to copy, use, sell and distribute this software is granted // provided this copyright notice appears in all copies. // Permission to modify the code and to distribute modified code is granted // provided this copyright notice appears in all copies, and a notice // that the code was modified is included with the copyright notice. // // This software is provided "as is" without express or implied warranty, // and with no claim as to its suitability for any purpose. // For more information, see http://www.boost.org /* Note: this header is a header template and must NOT have multiple-inclusion protection. */ #include #include namespace boost { namespace detail { namespace function { #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS template struct BOOST_FUNCTION_INVOKER_BASE { virtual ~BOOST_FUNCTION_INVOKER_BASE() {} virtual R call(BOOST_FUNCTION_PARMS) = 0; virtual R call(BOOST_FUNCTION_PARMS) const = 0; virtual BOOST_FUNCTION_INVOKER_BASE* clone() const = 0; virtual void destroy(BOOST_FUNCTION_INVOKER_BASE*) = 0; }; #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS template< typename FunctionPtr, #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename Allocator, #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_FUNCTION_INVOKER #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS : public BOOST_FUNCTION_INVOKER_BASE< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS { #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS explicit BOOST_FUNCTION_FUNCTION_INVOKER(FunctionPtr f) : function_ptr(f) {} virtual R call(BOOST_FUNCTION_PARMS) { return function_ptr(BOOST_FUNCTION_ARGS); } virtual R call(BOOST_FUNCTION_PARMS) const { return function_ptr(BOOST_FUNCTION_ARGS); } virtual BOOST_FUNCTION_FUNCTION_INVOKER* clone() const { # ifdef BOOST_NO_STD_ALLOCATOR return new BOOST_FUNCTION_FUNCTION_INVOKER(function_ptr); # else 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, *this); return static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR } virtual void destroy(BOOST_FUNCTION_INVOKER_BASE< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >* p) { # ifdef BOOST_NO_STD_ALLOCATOR delete p; # else BOOST_FUNCTION_FUNCTION_INVOKER* victim = dynamic_cast(p); typedef typename Allocator:: template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; allocator.destroy(victim); allocator.deallocate(victim, 1); # endif // BOOST_NO_STD_ALLOCATOR } private: FunctionPtr function_ptr; #else static R invoke(any_pointer function_ptr, bool BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) { FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); return f(BOOST_FUNCTION_ARGS); } #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template< typename FunctionPtr, # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename Allocator, # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS : public BOOST_FUNCTION_INVOKER_BASE< unusable BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS { # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS explicit BOOST_FUNCTION_VOID_FUNCTION_INVOKER(FunctionPtr f) : function_ptr(f) {} virtual unusable call(BOOST_FUNCTION_PARMS) { function_ptr(BOOST_FUNCTION_ARGS); return unusable(); } virtual unusable call(BOOST_FUNCTION_PARMS) const { function_ptr(BOOST_FUNCTION_ARGS); return unusable; } virtual BOOST_FUNCTION_VOID_FUNCTION_INVOKER* clone() const { # ifdef BOOST_NO_STD_ALLOCATOR return new BOOST_FUNCTION_VOID_FUNCTION_INVOKER(function_ptr); # else 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, *this); return static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR } virtual void destroy(BOOST_FUNCTION_INVOKER_BASE< unusable BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >* p) { # ifdef BOOST_NO_STD_ALLOCATOR delete p; # else BOOST_FUNCTION_VOID_FUNCTION_INVOKER* victim = dynamic_cast(p); typedef typename Allocator:: template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; allocator.destroy(victim); allocator.deallocate(victim, 1); # endif // BOOST_NO_STD_ALLOCATOR } private: FunctionPtr function_ptr; # else static unusable invoke(any_pointer function_ptr, bool BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) { FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); f(BOOST_FUNCTION_ARGS); return unusable(); } # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; #else template< typename FunctionPtr, # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename Allocator, # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS : public BOOST_FUNCTION_INVOKER_BASE< void BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS { # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS explicit BOOST_FUNCTION_VOID_FUNCTION_INVOKER(FunctionPtr f) : function_ptr(f) {} virtual void call(BOOST_FUNCTION_PARMS) { function_ptr(BOOST_FUNCTION_ARGS); } virtual void call(BOOST_FUNCTION_PARMS) const { function_ptr(BOOST_FUNCTION_ARGS); } virtual BOOST_FUNCTION_VOID_FUNCTION_INVOKER* clone() const { # ifdef BOOST_NO_STD_ALLOCATOR return new BOOST_FUNCTION_VOID_FUNCTION_INVOKER(function_ptr); # else 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, *this); return static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR } virtual void destroy(BOOST_FUNCTION_INVOKER_BASE< void BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >* p) { # ifdef BOOST_NO_STD_ALLOCATOR delete p; # else BOOST_FUNCTION_VOID_FUNCTION_INVOKER* victim = dynamic_cast(p); typedef typename Allocator:: template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; allocator.destroy(victim); allocator.deallocate(victim, 1); # endif // BOOST_NO_STD_ALLOCATOR } private: FunctionPtr function_ptr; # else static void invoke(any_pointer function_ptr, bool BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) { FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); f(BOOST_FUNCTION_ARGS); } # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template< typename FunctionObj, #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename Allocator, #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS : public BOOST_FUNCTION_INVOKER_BASE< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS { #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS explicit BOOST_FUNCTION_FUNCTION_OBJ_INVOKER(const FunctionObj& f) : function_obj(f) {} virtual R call(BOOST_FUNCTION_PARMS) { return function_obj(BOOST_FUNCTION_ARGS); } virtual R call(BOOST_FUNCTION_PARMS) const { return function_obj(BOOST_FUNCTION_ARGS); } virtual BOOST_FUNCTION_FUNCTION_OBJ_INVOKER* clone() const { #ifdef BOOST_NO_STD_ALLOCATOR return new BOOST_FUNCTION_FUNCTION_OBJ_INVOKER(function_obj); #else 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, *this); return static_cast(copy); #endif // BOOST_NO_STD_ALLOCATOR } virtual void destroy(BOOST_FUNCTION_INVOKER_BASE< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >* p) { #ifdef BOOST_NO_STD_ALLOCATOR delete p; #else BOOST_FUNCTION_FUNCTION_OBJ_INVOKER* victim = dynamic_cast(p); typedef typename Allocator:: template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; allocator.destroy(victim); allocator.deallocate(victim, 1); #endif // BOOST_NO_STD_ALLOCATOR } private: FunctionObj function_obj; #else static R invoke(any_pointer function_obj_ptr, bool is_const BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) { FunctionObj* f = static_cast(function_obj_ptr.obj_ptr); if (is_const) { const FunctionObj* fc = f; return (*fc)(BOOST_FUNCTION_ARGS); } else { return (*f)(BOOST_FUNCTION_ARGS); } } #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template< typename FunctionObj, # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename Allocator, # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS : public BOOST_FUNCTION_INVOKER_BASE< unusable BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS { # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS explicit BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER(const FunctionObj& f) : function_obj(f) {} virtual unusable call(BOOST_FUNCTION_PARMS) { function_obj(BOOST_FUNCTION_ARGS); return unusable(); } virtual unusable call(BOOST_FUNCTION_PARMS) const { function_obj(BOOST_FUNCTION_ARGS); return unusable(); } virtual BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER* clone() const { #ifdef BOOST_NO_STD_ALLOCATOR return new BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER(function_obj); #else 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, *this); return static_cast(copy); #endif // BOOST_NO_STD_ALLOCATOR } virtual void destroy(BOOST_FUNCTION_INVOKER_BASE< unusable BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >* p) { #ifdef BOOST_NO_STD_ALLOCATOR delete p; #else BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER* victim = dynamic_cast(p); typedef typename Allocator:: template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; allocator.destroy(victim); allocator.deallocate(victim, 1); #endif // BOOST_NO_STD_ALLOCATOR } private: FunctionObj function_obj; # else static unusable invoke(any_pointer function_obj_ptr, bool is_const BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) { FunctionObj* f = static_cast(function_obj_ptr.obj_ptr); if (is_const) { const FunctionObj* fc = f; (*fc)(BOOST_FUNCTION_ARGS); } else { (*f)(BOOST_FUNCTION_ARGS); } return unusable(); } # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; #else template< typename FunctionObj, #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename Allocator, #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS : public BOOST_FUNCTION_INVOKER_BASE< void BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS { # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS explicit BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER(const FunctionObj& f) : function_obj(f) {} virtual void call(BOOST_FUNCTION_PARMS) { function_obj(BOOST_FUNCTION_ARGS); } virtual void call(BOOST_FUNCTION_PARMS) const { function_obj(BOOST_FUNCTION_ARGS); } virtual BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER * clone() const { # ifdef BOOST_NO_STD_ALLOCATOR return new BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER (function_obj); # else 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, *this); return static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR } virtual void destroy(BOOST_FUNCTION_INVOKER_BASE< void BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >* p) { #ifdef BOOST_NO_STD_ALLOCATOR delete p; #else BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER* victim = dynamic_cast(p); typedef typename Allocator:: template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; allocator.destroy(victim); allocator.deallocate(victim, 1); #endif // BOOST_NO_STD_ALLOCATOR } private: FunctionObj function_obj; # else static void invoke(any_pointer function_obj_ptr, bool is_const BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) { FunctionObj* f = static_cast(function_obj_ptr.obj_ptr); if (is_const) { const FunctionObj* fc = f; (*fc)(BOOST_FUNCTION_ARGS); } else { (*f)(BOOST_FUNCTION_ARGS); } } # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; #endif template< typename FunctionPtr, typename Allocator, typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_GET_FUNCTION_INVOKER { typedef typename IF<(is_void::value), BOOST_FUNCTION_VOID_FUNCTION_INVOKER< FunctionPtr, #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS Allocator, #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >, BOOST_FUNCTION_FUNCTION_INVOKER< FunctionPtr, #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS Allocator, #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > >::type type; }; template< typename FunctionObj, typename Allocator, typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER { typedef typename IF<(is_void::value), BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER< FunctionObj, #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS Allocator, #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >, BOOST_FUNCTION_FUNCTION_OBJ_INVOKER< FunctionObj, #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS Allocator, #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > >::type type; }; } // end namespace function } // end namespace detail template< typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, typename Policy = empty_function_policy, typename Mixin = empty_function_mixin, typename Allocator = std::allocator > class BOOST_FUNCTION_FUNCTION : public function_base, public Mixin { public: BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); typedef typename detail::function::function_return_type::type result_type; typedef Policy policy_type; typedef Mixin mixin_type; typedef Allocator allocator_type; #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS private: typedef detail::function::BOOST_FUNCTION_INVOKER_BASE< result_type BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > impl_type; public: #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS // Construct without a target BOOST_FUNCTION_FUNCTION() : function_base() {} #else // Construct without a target BOOST_FUNCTION_FUNCTION() : function_base() # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS , invoker(0) # endif { } #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING // Clone the functor target f and make the clone the target template BOOST_FUNCTION_FUNCTION(Functor BOOST_MSVC_INCLUDE(const &) f) : function_base() # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS , invoker(0) # endif { if (!detail::function::has_empty_target(f)) assign_to(f); } #else template BOOST_FUNCTION_FUNCTION(const Functor& f) : function_base() # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS , invoker(0) # endif { if (!detail::function::has_empty_target(&f)) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< Functor, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(const_cast(&f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } template BOOST_FUNCTION_FUNCTION(OtherR (*f)( BOOST_FUNCTION_OTHER_TEMPLATE_ARGS )) : function_base() # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS , invoker(0) # endif { if (f) { typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS); typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< FunctionPtr, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager ::manage; functor = manager(detail::function::any_pointer(reinterpret_cast(f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } #endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING // Clone the input BOOST_FUNCTION_FUNCTION's target BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f): function_base() # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS , invoker(0) # endif { if (!f.empty()) { # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS impl_type* other_impl = reinterpret_cast(f.impl); impl = static_cast(other_impl->clone()); # else invoker = f.invoker; manager = f.manager; functor = f.manager(f.functor, detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } // Destroy the target, if there is one ~BOOST_FUNCTION_FUNCTION() { clear(); } void swap(BOOST_FUNCTION_FUNCTION& other) { #ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS std::swap(manager, other.manager); std::swap(functor, other.functor); std::swap(invoker, other.invoker); #else std::swap(impl, other.impl); #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } // Invoke the target result_type operator()(BOOST_FUNCTION_PARMS) { assert(!this->empty()); policy_type policy; policy.precall(this); #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS impl_type* i = reinterpret_cast(impl); result_type result = i->call(BOOST_FUNCTION_ARGS); #else result_type result = invoker(functor, false BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS policy.postcall(this); return result; } result_type operator()(BOOST_FUNCTION_PARMS) const { assert(!this->empty()); policy_type policy; policy.precall(this); #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS const impl_type* i = reinterpret_cast(impl); result_type result = i->call(BOOST_FUNCTION_ARGS); #else result_type result = invoker(functor, true BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS policy.postcall(this); return result; } // Clear out a target, if there is one void clear() { #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS if (impl) { impl_type* i = reinterpret_cast(impl); i->destroy(i); impl = 0; } #else if (manager) functor = manager(functor, detail::function::destroy_functor); manager = 0; invoker = 0; #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } #ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING // Assignment from any functor template BOOST_FUNCTION_FUNCTION& operator=(Functor BOOST_MSVC_INCLUDE(const &) f) { clear(); if (!detail::function::has_empty_target(f)) { // MSVC 6 eats the ';', so add another ';'. Don't ask me why. assign_to(f);; } return *this; } #else template BOOST_FUNCTION_FUNCTION& operator=(const Functor& f) { clear(); if (!detail::function::has_empty_target(&f)) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< Functor, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(const_cast(&f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } return *this; } template BOOST_FUNCTION_FUNCTION& operator=(OtherR (*f)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS)) { clear(); if (f) { typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS); typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< FunctionPtr, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(reinterpret_cast(f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } return *this; } #endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING #ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING // Assignment from any functor template void set(Functor BOOST_MSVC_INCLUDE(const &) f) { clear(); if (!detail::function::has_empty_target(f)) { // MSVC 6 eats the ';', so add another ';'. Don't ask me why. assign_to(f);; } } #else template void set(const Functor& f) { clear(); if (!detail::function::has_empty_target(&f)) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< Functor, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(const_cast(&f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } template void set(OtherR (*f)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS)) { clear(); if (f) { typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS); typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< FunctionPtr, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager ::manage; functor = manager(detail::function::any_pointer(reinterpret_cast(f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } #endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING // Assignment from another BOOST_FUNCTION_FUNCTION BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) { clear(); if (!f.empty()) { # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS const impl_type* other_impl = reinterpret_cast(f.impl); impl = static_cast(other_impl->clone()); # else invoker = f.invoker; manager = f.manager; functor = f.manager? f.manager(f.functor, detail::function::clone_functor) : f.functor; # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } return *this; } // Assignment from another BOOST_FUNCTION_FUNCTION void set(const BOOST_FUNCTION_FUNCTION& f) { clear(); if (!f.empty()) { # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS const impl_type* other_impl = reinterpret_cast(f.impl); impl = static_cast(other_impl->clone()); # else invoker = f.invoker; manager = f.manager; functor = f.manager? f.manager(f.functor, detail::function::clone_functor) : f.functor; # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } protected: #if defined BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING || defined BOOST_NO_DEPENDENT_BASE_LOOKUP # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS // Clone a function pointer template void* clone_functor(FunctionPtr f, detail::function::function_ptr_tag) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< FunctionPtr, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR return static_cast(i); } // Clone a function object template void* clone_functor(FunctionObj& f, detail::function::function_obj_tag) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< FunctionObj, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR return static_cast(i); } # else // Clone a function pointer template detail::function::any_pointer clone_functor(FunctionPtr f, detail::function::function_ptr_tag) { detail::function::any_pointer a(reinterpret_cast(f)); return manager(a, detail::function::clone_functor); } // Clone a functor template detail::function::any_pointer clone_functor(FunctionObj& f, detail::function::function_obj_tag) { detail::function::any_pointer a(static_cast(&f)); return manager(a, detail::function::clone_functor); } # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS // Assign this BOOST_FUNCTION_FUNCTION to the given functor template void assign_to(Functor f) { // Do we have a functor or a function pointer? typedef typename detail::function::IF< (is_pointer::value), detail::function::function_ptr_tag, detail::function::function_obj_tag>::RET target_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS impl = clone_functor(f, target_type()); # else typedef typename detail::function::IF<(is_pointer::value), detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< Functor, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >, detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< Functor, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > >::type invoker_selector; typedef typename invoker_selector::type invoker_type; // Setup the new functor invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = clone_functor(f, target_type()); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } #endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING #ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typedef result_type (*invoker_type)(detail::function::any_pointer, bool BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS ); invoker_type invoker; #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; #ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template< BOOST_FUNCTION_TEMPLATE_PARMS BOOST_FUNCTION_COMMA typename Policy, typename Mixin, typename Allocator > class BOOST_FUNCTION_FUNCTION< void BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Policy, Mixin, Allocator> : public function_base, public Mixin { public: BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); typedef void result_type; typedef void R; typedef Policy policy_type; typedef Mixin mixin_type; typedef Allocator allocator_type; #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS private: typedef detail::function::BOOST_FUNCTION_INVOKER_BASE< result_type BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > impl_type; public: #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS // Construct without a target BOOST_FUNCTION_FUNCTION() : function_base() {} #else // Construct without a target BOOST_FUNCTION_FUNCTION() : function_base() # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS , invoker(0) # endif { } #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS #ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING // Clone the functor target f and make the clone the target template BOOST_FUNCTION_FUNCTION(Functor BOOST_MSVC_INCLUDE(const &) f) : function_base() # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS , invoker(0) # endif { if (!detail::function::has_empty_target(f)) assign_to(f); } #else template BOOST_FUNCTION_FUNCTION(const Functor& f) : function_base() # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS , invoker(0) # endif { if (!detail::function::has_empty_target(&f)) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< Functor, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(const_cast(&f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } template BOOST_FUNCTION_FUNCTION(OtherR (*f)( BOOST_FUNCTION_OTHER_TEMPLATE_ARGS )) : function_base() # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS , invoker(0) # endif { if (f) { typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS); typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< FunctionPtr, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(reinterpret_cast(f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } #endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING // Clone the input BOOST_FUNCTION_FUNCTION's target BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f): function_base() # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS , invoker(0) # endif { if (!f.empty()) { # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS impl_type* other_impl = reinterpret_cast(f.impl); impl = static_cast(other_impl->clone()); # else invoker = f.invoker; manager = f.manager; functor = f.manager(f.functor, detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } // Destroy the target, if there is one ~BOOST_FUNCTION_FUNCTION() { clear(); } void swap(BOOST_FUNCTION_FUNCTION& other) { # ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS std::swap(manager, other.manager); std::swap(functor, other.functor); std::swap(invoker, other.invoker); # else std::swap(impl, other.impl); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } // Invoke the target result_type operator()(BOOST_FUNCTION_PARMS) { assert(!this->empty()); policy_type policy; policy.precall(this); #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS impl_type* i = reinterpret_cast(impl); i->call(BOOST_FUNCTION_ARGS); #else invoker(functor, false BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS policy.postcall(this); } result_type operator()(BOOST_FUNCTION_PARMS) const { assert(!this->empty()); policy_type policy; policy.precall(this); #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS const impl_type* i = reinterpret_cast(impl); i->call(BOOST_FUNCTION_ARGS); #else invoker(functor, true BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS policy.postcall(this); } // Clear out a target, if there is one void clear() { #ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS if (impl) { impl_type* i = reinterpret_cast(impl); i->destroy(i); impl = 0; } #else if (manager) functor = manager(functor, detail::function::destroy_functor); manager = 0; invoker = 0; #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } #ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING // Assignment from any functor template BOOST_FUNCTION_FUNCTION& operator=(Functor BOOST_MSVC_INCLUDE(const &) f) { clear(); if (!detail::function::has_empty_target(f)) { // MSVC 6 eats the ';', so add another ';'. Don't ask me why. assign_to(f);; } return *this; } #else template BOOST_FUNCTION_FUNCTION& operator=(const Functor& f) { clear(); if (!detail::function::has_empty_target(&f)) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< Functor, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(const_cast(&f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } return *this; } template BOOST_FUNCTION_FUNCTION& operator=(OtherR (*f)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS)) { clear(); if (f) { typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS); typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< FunctionPtr, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(reinterpret_cast(f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } return *this; } #endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING #ifdef BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING // Assignment from any functor template void set(Functor BOOST_MSVC_INCLUDE(const &) f) { clear(); if (!detail::function::has_empty_target(f)) { // MSVC 6 eats the ';', so add another ';'. Don't ask me why. assign_to(f);; } } #else template void set(const Functor& f) { clear(); if (!detail::function::has_empty_target(&f)) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< Functor, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(const_cast(&f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } template void set(OtherR (*f)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS)) { clear(); if (f) { typedef OtherR (*FunctionPtr)(BOOST_FUNCTION_OTHER_TEMPLATE_ARGS); typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< FunctionPtr, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR impl = static_cast(i); # else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(reinterpret_cast(f)), detail::function::clone_functor); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } #endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING // Assignment from another BOOST_FUNCTION_FUNCTION BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) { clear(); if (!f.empty()) { # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS const impl_type* other_impl = reinterpret_cast(f.impl); impl = static_cast(other_impl->clone()); # else invoker = f.invoker; manager = f.manager; functor = f.manager? f.manager(f.functor, detail::function::clone_functor) : f.functor; # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } return *this; } // Assignment from another BOOST_FUNCTION_FUNCTION void set(const BOOST_FUNCTION_FUNCTION& f) { clear(); if (!f.empty()) { # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS const impl_type* other_impl = reinterpret_cast(f.impl); impl = static_cast(other_impl->clone()); # else invoker = f.invoker; manager = f.manager; functor = f.manager? f.manager(f.functor, detail::function::clone_functor) : f.functor; # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } protected: #if defined BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING || defined BOOST_NO_DEPENDENT_BASE_LOOKUP # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS // Clone a function pointer template void* clone_functor(FunctionPtr f, detail::function::function_ptr_tag) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< FunctionPtr, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR return static_cast(i); } // Clone a function object template void* clone_functor(FunctionObj& f, detail::function::function_obj_tag) { typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< FunctionObj, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >::type invoker_type; # ifdef BOOST_NO_STD_ALLOCATOR impl_type* i = new invoker_type(f); # else typedef typename Allocator::template rebind::other allocator_type; typedef typename allocator_type::pointer pointer_type; allocator_type allocator; pointer_type copy = allocator.allocate(1); new (copy) invoker_type(f); impl_type* i = static_cast(copy); # endif // BOOST_NO_STD_ALLOCATOR return static_cast(i); } # else // Clone a function pointer template detail::function::any_pointer clone_functor(FunctionPtr f, detail::function::function_ptr_tag) { detail::function::any_pointer a(reinterpret_cast(f)); return manager(a, detail::function::clone_functor); } // Clone a functor template detail::function::any_pointer clone_functor(FunctionObj& f, detail::function::function_obj_tag) { detail::function::any_pointer a(static_cast(&f)); return manager(a, detail::function::clone_functor); } # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS // Assign this BOOST_FUNCTION_FUNCTION to the given functor template void assign_to(Functor f) { // Do we have a functor or a function pointer? typedef typename detail::function::IF<(is_pointer::value), detail::function::function_ptr_tag, detail::function::function_obj_tag>::RET target_type; # ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS impl = clone_functor(f, target_type()); # else typedef typename detail::function::IF<(is_pointer::value), detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER< Functor, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >, detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< Functor, Allocator, R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > >::type invoker_selector; typedef typename invoker_selector::type invoker_type; // Setup the new functor invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = clone_functor(f, target_type()); # endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } #endif // BOOST_WEAK_FUNCTION_TEMPLATE_ORDERING #ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typedef result_type (*invoker_type)(detail::function::any_pointer, bool BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS ); invoker_type invoker; #endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; #endif // BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template inline void swap(BOOST_FUNCTION_FUNCTION< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS , Policy, Mixin, Allocator >& f1, BOOST_FUNCTION_FUNCTION< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Policy, Mixin, Allocator >& f2) { f1.swap(f2); } }