williamr@2: // Boost.Function library williamr@2: williamr@2: // Copyright Douglas Gregor 2001-2006. Use, modification and williamr@2: // distribution is subject to the Boost Software License, Version williamr@2: // 1.0. (See accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: williamr@2: // For more information, see http://www.boost.org williamr@2: williamr@2: // Note: this header is a header template and must NOT have multiple-inclusion williamr@2: // protection. williamr@2: #include williamr@2: williamr@2: #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) williamr@2: williamr@2: #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T) williamr@2: williamr@2: #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I) williamr@2: williamr@2: #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY) williamr@2: williamr@2: #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a) williamr@2: williamr@2: #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \ williamr@2: typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type); williamr@2: williamr@2: #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY) williamr@2: williamr@2: // Type of the default allocator williamr@2: #ifndef BOOST_NO_STD_ALLOCATOR williamr@2: # define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator williamr@2: #else williamr@2: # define BOOST_FUNCTION_DEFAULT_ALLOCATOR int williamr@2: #endif // BOOST_NO_STD_ALLOCATOR williamr@2: williamr@2: // Comma if nonzero number of arguments williamr@2: #if BOOST_FUNCTION_NUM_ARGS == 0 williamr@2: # define BOOST_FUNCTION_COMMA williamr@2: #else williamr@2: # define BOOST_FUNCTION_COMMA , williamr@2: #endif // BOOST_FUNCTION_NUM_ARGS > 0 williamr@2: williamr@2: // Class names used in this version of the code williamr@2: #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS) williamr@2: #define BOOST_FUNCTION_FUNCTION_INVOKER \ williamr@2: BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) williamr@2: #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ williamr@2: BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS) williamr@2: #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \ williamr@2: BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) williamr@2: #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \ williamr@2: BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) williamr@2: #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \ williamr@2: BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) williamr@2: #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \ williamr@2: BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) williamr@2: #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ williamr@2: BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) williamr@2: #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ williamr@2: BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) williamr@2: #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \ williamr@2: BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) williamr@2: #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS) williamr@2: williamr@2: #ifndef BOOST_NO_VOID_RETURNS williamr@2: # define BOOST_FUNCTION_VOID_RETURN_TYPE void williamr@2: # define BOOST_FUNCTION_RETURN(X) X williamr@2: #else williamr@2: # define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable williamr@2: # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE () williamr@2: #endif williamr@2: williamr@2: #ifdef BOOST_MSVC williamr@2: # pragma warning(push) williamr@2: # pragma warning(disable: 4127) // conditional expression is constant. williamr@2: #endif williamr@2: williamr@2: #ifdef BOOST_MSVC williamr@2: # pragma warning(push) williamr@2: # pragma warning(disable: 4127) // conditional expression is constant. williamr@2: #endif williamr@2: williamr@2: namespace boost { williamr@2: namespace detail { williamr@2: namespace function { williamr@2: template< williamr@2: typename FunctionPtr, williamr@2: typename R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_PARMS williamr@2: > williamr@2: struct BOOST_FUNCTION_FUNCTION_INVOKER williamr@2: { williamr@2: static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_PARMS) williamr@2: { williamr@2: FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); williamr@2: return f(BOOST_FUNCTION_ARGS); williamr@2: } williamr@2: }; williamr@2: williamr@2: template< williamr@2: typename FunctionPtr, williamr@2: typename R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_PARMS williamr@2: > williamr@2: struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER williamr@2: { williamr@2: static BOOST_FUNCTION_VOID_RETURN_TYPE williamr@2: invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_PARMS) williamr@2: williamr@2: { williamr@2: FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); williamr@2: BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS)); williamr@2: } williamr@2: }; williamr@2: williamr@2: template< williamr@2: typename FunctionObj, williamr@2: typename R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_PARMS williamr@2: > williamr@2: struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER williamr@2: { williamr@2: static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_PARMS) williamr@2: williamr@2: { williamr@2: FunctionObj* f; williamr@2: if (function_allows_small_object_optimization::value) williamr@2: f = reinterpret_cast(&function_obj_ptr.data); williamr@2: else williamr@2: f = reinterpret_cast(function_obj_ptr.obj_ptr); williamr@2: return (*f)(BOOST_FUNCTION_ARGS); williamr@2: } williamr@2: }; williamr@2: williamr@2: template< williamr@2: typename FunctionObj, williamr@2: typename R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_PARMS williamr@2: > williamr@2: struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER williamr@2: { williamr@2: static BOOST_FUNCTION_VOID_RETURN_TYPE williamr@2: invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_PARMS) williamr@2: williamr@2: { williamr@2: FunctionObj* f; williamr@2: if (function_allows_small_object_optimization::value) williamr@2: f = reinterpret_cast(&function_obj_ptr.data); williamr@2: else williamr@2: f = reinterpret_cast(function_obj_ptr.obj_ptr); williamr@2: BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); williamr@2: } williamr@2: }; williamr@2: williamr@2: template< williamr@2: typename FunctionObj, williamr@2: typename R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_PARMS williamr@2: > williamr@2: struct BOOST_FUNCTION_FUNCTION_REF_INVOKER williamr@2: { williamr@2: static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_PARMS) williamr@2: williamr@2: { williamr@2: FunctionObj* f = williamr@2: reinterpret_cast(function_obj_ptr.obj_ptr); williamr@2: return (*f)(BOOST_FUNCTION_ARGS); williamr@2: } williamr@2: }; williamr@2: williamr@2: template< williamr@2: typename FunctionObj, williamr@2: typename R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_PARMS williamr@2: > williamr@2: struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER williamr@2: { williamr@2: static BOOST_FUNCTION_VOID_RETURN_TYPE williamr@2: invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_PARMS) williamr@2: williamr@2: { williamr@2: FunctionObj* f = williamr@2: reinterpret_cast(function_obj_ptr.obj_ptr); williamr@2: BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); williamr@2: } williamr@2: }; williamr@2: williamr@2: template< williamr@2: typename FunctionPtr, williamr@2: typename R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_PARMS williamr@2: > williamr@2: struct BOOST_FUNCTION_GET_FUNCTION_INVOKER williamr@2: { williamr@2: typedef typename mpl::if_c<(is_void::value), williamr@2: BOOST_FUNCTION_VOID_FUNCTION_INVOKER< williamr@2: FunctionPtr, williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS williamr@2: >, williamr@2: BOOST_FUNCTION_FUNCTION_INVOKER< williamr@2: FunctionPtr, williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS williamr@2: > williamr@2: >::type type; williamr@2: }; williamr@2: williamr@2: template< williamr@2: typename FunctionObj, williamr@2: typename R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_PARMS williamr@2: > williamr@2: struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER williamr@2: { williamr@2: typedef typename mpl::if_c<(is_void::value), williamr@2: BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER< williamr@2: FunctionObj, williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS williamr@2: >, williamr@2: BOOST_FUNCTION_FUNCTION_OBJ_INVOKER< williamr@2: FunctionObj, williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS williamr@2: > williamr@2: >::type type; williamr@2: }; williamr@2: williamr@2: template< williamr@2: typename FunctionObj, williamr@2: typename R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_PARMS williamr@2: > williamr@2: struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER williamr@2: { williamr@2: typedef typename mpl::if_c<(is_void::value), williamr@2: BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER< williamr@2: FunctionObj, williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS williamr@2: >, williamr@2: BOOST_FUNCTION_FUNCTION_REF_INVOKER< williamr@2: FunctionObj, williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS williamr@2: > williamr@2: >::type type; williamr@2: }; williamr@2: williamr@2: /** williamr@2: * vtable for a specific boost::function instance. williamr@2: */ williamr@2: template williamr@2: struct BOOST_FUNCTION_VTABLE : vtable_base williamr@2: { williamr@2: #ifndef BOOST_NO_VOID_RETURNS williamr@2: typedef R result_type; williamr@2: #else williamr@2: typedef typename function_return_type::type result_type; williamr@2: #endif // BOOST_NO_VOID_RETURNS williamr@2: williamr@2: typedef result_type (*invoker_type)(function_buffer& williamr@2: BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS); williamr@2: williamr@2: template williamr@2: BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0) williamr@2: { williamr@2: init(f); williamr@2: } williamr@2: williamr@2: template williamr@2: bool assign_to(F f, function_buffer& functor) williamr@2: { williamr@2: typedef typename get_function_tag::type tag; williamr@2: return assign_to(f, functor, tag()); williamr@2: } williamr@2: williamr@2: void clear(function_buffer& functor) williamr@2: { williamr@2: if (manager) williamr@2: manager(functor, functor, destroy_functor_tag); williamr@2: } williamr@2: williamr@2: private: williamr@2: template williamr@2: void init(F f) williamr@2: { williamr@2: typedef typename get_function_tag::type tag; williamr@2: init(f, tag()); williamr@2: } williamr@2: williamr@2: // Function pointers williamr@2: template williamr@2: void init(FunctionPtr /*f*/, function_ptr_tag) williamr@2: { williamr@2: typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< williamr@2: FunctionPtr, williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS williamr@2: >::type williamr@2: actual_invoker_type; williamr@2: williamr@2: invoker = &actual_invoker_type::invoke; williamr@2: manager = &functor_manager::manage; williamr@2: } williamr@2: williamr@2: template williamr@2: bool williamr@2: assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) williamr@2: { williamr@2: this->clear(functor); williamr@2: if (f) { williamr@2: // should be a reinterpret cast, but some compilers insist williamr@2: // on giving cv-qualifiers to free functions williamr@2: functor.func_ptr = (void (*)())(f); williamr@2: return true; williamr@2: } else { williamr@2: return false; williamr@2: } williamr@2: } williamr@2: williamr@2: // Member pointers williamr@2: #if BOOST_FUNCTION_NUM_ARGS > 0 williamr@2: template williamr@2: void init(MemberPtr f, member_ptr_tag) williamr@2: { williamr@2: // DPG TBD: Add explicit support for member function williamr@2: // objects, so we invoke through mem_fn() but we retain the williamr@2: // right target_type() values. williamr@2: this->init(mem_fn(f)); williamr@2: } williamr@2: williamr@2: template williamr@2: bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) williamr@2: { williamr@2: // DPG TBD: Add explicit support for member function williamr@2: // objects, so we invoke through mem_fn() but we retain the williamr@2: // right target_type() values. williamr@2: if (f) { williamr@2: this->assign_to(mem_fn(f), functor); williamr@2: return true; williamr@2: } else { williamr@2: return false; williamr@2: } williamr@2: } williamr@2: #endif // BOOST_FUNCTION_NUM_ARGS > 0 williamr@2: williamr@2: // Function objects williamr@2: template williamr@2: void init(FunctionObj /*f*/, function_obj_tag) williamr@2: { williamr@2: typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< williamr@2: FunctionObj, williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS williamr@2: >::type williamr@2: actual_invoker_type; williamr@2: williamr@2: invoker = &actual_invoker_type::invoke; williamr@2: manager = &functor_manager::manage; williamr@2: } williamr@2: williamr@2: // Assign to a function object using the small object optimization williamr@2: template williamr@2: void williamr@2: assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) williamr@2: { williamr@2: new ((void*)&functor.data) FunctionObj(f); williamr@2: } williamr@2: williamr@2: // Assign to a function object allocated on the heap. williamr@2: template williamr@2: void williamr@2: assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) williamr@2: { williamr@2: #ifndef BOOST_NO_STD_ALLOCATOR williamr@2: typedef typename Allocator::template rebind::other williamr@2: allocator_type; williamr@2: typedef typename allocator_type::pointer pointer_type; williamr@2: williamr@2: allocator_type allocator; williamr@2: pointer_type copy = allocator.allocate(1); williamr@2: allocator.construct(copy, f); williamr@2: williamr@2: // Get back to the original pointer type williamr@2: functor.obj_ptr = static_cast(copy); williamr@2: # else williamr@2: functor.obj_ptr = new FunctionObj(f); williamr@2: # endif // BOOST_NO_STD_ALLOCATOR williamr@2: } williamr@2: williamr@2: template williamr@2: bool williamr@2: assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) williamr@2: { williamr@2: if (!boost::detail::function::has_empty_target(boost::addressof(f))) { williamr@2: assign_functor(f, functor, williamr@2: mpl::bool_<(function_allows_small_object_optimization::value)>()); williamr@2: return true; williamr@2: } else { williamr@2: return false; williamr@2: } williamr@2: } williamr@2: williamr@2: // Reference to a function object williamr@2: template williamr@2: void williamr@2: init(const reference_wrapper& /*f*/, function_obj_ref_tag) williamr@2: { williamr@2: typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< williamr@2: FunctionObj, williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS williamr@2: >::type williamr@2: actual_invoker_type; williamr@2: williamr@2: invoker = &actual_invoker_type::invoke; williamr@2: manager = &reference_manager::get; williamr@2: } williamr@2: williamr@2: template williamr@2: bool williamr@2: assign_to(const reference_wrapper& f, williamr@2: function_buffer& functor, function_obj_ref_tag) williamr@2: { williamr@2: if (!boost::detail::function::has_empty_target(f.get_pointer())) { williamr@2: // DPG TBD: We might need to detect constness of williamr@2: // FunctionObj to assign into obj_ptr or const_obj_ptr to williamr@2: // be truly legit, but no platform in existence makes williamr@2: // const void* different from void*. williamr@2: functor.const_obj_ptr = f.get_pointer(); williamr@2: return true; williamr@2: } else { williamr@2: return false; williamr@2: } williamr@2: } williamr@2: williamr@2: public: williamr@2: invoker_type invoker; williamr@2: }; williamr@2: } // end namespace function williamr@2: } // end namespace detail williamr@2: williamr@2: template< williamr@2: typename R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_PARMS, williamr@2: typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR williamr@2: > williamr@2: class BOOST_FUNCTION_FUNCTION : public function_base williamr@2: { williamr@2: public: williamr@2: #ifndef BOOST_NO_VOID_RETURNS williamr@2: typedef R result_type; williamr@2: #else williamr@2: typedef typename boost::detail::function::function_return_type::type williamr@2: result_type; williamr@2: #endif // BOOST_NO_VOID_RETURNS williamr@2: williamr@2: private: williamr@2: typedef boost::detail::function::BOOST_FUNCTION_VTABLE< williamr@2: R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Allocator> williamr@2: vtable_type; williamr@2: williamr@2: struct clear_type {}; williamr@2: williamr@2: public: williamr@2: BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); williamr@2: williamr@2: // add signature for boost::lambda williamr@2: template williamr@2: struct sig williamr@2: { williamr@2: typedef result_type type; williamr@2: }; williamr@2: williamr@2: #if BOOST_FUNCTION_NUM_ARGS == 1 williamr@2: typedef T0 argument_type; williamr@2: #elif BOOST_FUNCTION_NUM_ARGS == 2 williamr@2: typedef T0 first_argument_type; williamr@2: typedef T1 second_argument_type; williamr@2: #endif williamr@2: williamr@2: BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS); williamr@2: BOOST_FUNCTION_ARG_TYPES williamr@2: williamr@2: typedef Allocator allocator_type; williamr@2: typedef BOOST_FUNCTION_FUNCTION self_type; williamr@2: williamr@2: BOOST_FUNCTION_FUNCTION() : function_base() { } williamr@2: williamr@2: // MSVC chokes if the following two constructors are collapsed into williamr@2: // one with a default parameter. williamr@2: template williamr@2: BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f williamr@2: #ifndef BOOST_NO_SFINAE williamr@2: ,typename enable_if_c< williamr@2: (boost::type_traits::ice_not< williamr@2: (is_integral::value)>::value), williamr@2: int>::type = 0 williamr@2: #endif // BOOST_NO_SFINAE williamr@2: ) : williamr@2: function_base() williamr@2: { williamr@2: this->assign_to(f); williamr@2: } williamr@2: williamr@2: #ifndef BOOST_NO_SFINAE williamr@2: BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { } williamr@2: #else williamr@2: BOOST_FUNCTION_FUNCTION(int zero) : function_base() williamr@2: { williamr@2: BOOST_ASSERT(zero == 0); williamr@2: } williamr@2: #endif williamr@2: williamr@2: BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base() williamr@2: { williamr@2: this->assign_to_own(f); williamr@2: } williamr@2: williamr@2: ~BOOST_FUNCTION_FUNCTION() { clear(); } williamr@2: williamr@2: #if BOOST_WORKAROUND(BOOST_MSVC, < 1300) williamr@2: // MSVC 6.0 and prior require all definitions to be inline, but williamr@2: // these definitions can become very costly. williamr@2: result_type operator()(BOOST_FUNCTION_PARMS) const williamr@2: { williamr@2: if (this->empty()) williamr@2: boost::throw_exception(bad_function_call()); williamr@2: williamr@2: return static_cast(vtable)->invoker williamr@2: (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); williamr@2: } williamr@2: #else williamr@2: result_type operator()(BOOST_FUNCTION_PARMS) const; williamr@2: #endif williamr@2: williamr@2: // The distinction between when to use BOOST_FUNCTION_FUNCTION and williamr@2: // when to use self_type is obnoxious. MSVC cannot handle self_type as williamr@2: // the return type of these assignment operators, but Borland C++ cannot williamr@2: // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to williamr@2: // construct. williamr@2: template williamr@2: #ifndef BOOST_NO_SFINAE williamr@2: typename enable_if_c< williamr@2: (boost::type_traits::ice_not< williamr@2: (is_integral::value)>::value), williamr@2: BOOST_FUNCTION_FUNCTION&>::type williamr@2: #else williamr@2: BOOST_FUNCTION_FUNCTION& williamr@2: #endif williamr@2: operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) williamr@2: { williamr@2: this->clear(); williamr@2: try { williamr@2: this->assign_to(f); williamr@2: } catch (...) { williamr@2: vtable = 0; williamr@2: throw; williamr@2: } williamr@2: return *this; williamr@2: } williamr@2: williamr@2: #ifndef BOOST_NO_SFINAE williamr@2: BOOST_FUNCTION_FUNCTION& operator=(clear_type*) williamr@2: { williamr@2: this->clear(); williamr@2: return *this; williamr@2: } williamr@2: #else williamr@2: BOOST_FUNCTION_FUNCTION& operator=(int zero) williamr@2: { williamr@2: BOOST_ASSERT(zero == 0); williamr@2: this->clear(); williamr@2: return *this; williamr@2: } williamr@2: #endif williamr@2: williamr@2: // Assignment from another BOOST_FUNCTION_FUNCTION williamr@2: BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) williamr@2: { williamr@2: if (&f == this) williamr@2: return *this; williamr@2: williamr@2: this->clear(); williamr@2: try { williamr@2: this->assign_to_own(f); williamr@2: } catch (...) { williamr@2: vtable = 0; williamr@2: throw; williamr@2: } williamr@2: return *this; williamr@2: } williamr@2: williamr@2: void swap(BOOST_FUNCTION_FUNCTION& other) williamr@2: { williamr@2: if (&other == this) williamr@2: return; williamr@2: williamr@2: BOOST_FUNCTION_FUNCTION tmp = *this; williamr@2: *this = other; williamr@2: other = tmp; williamr@2: } williamr@2: williamr@2: // Clear out a target, if there is one williamr@2: void clear() williamr@2: { williamr@2: if (vtable) { williamr@2: static_cast(vtable)->clear(this->functor); williamr@2: vtable = 0; williamr@2: } williamr@2: } williamr@2: williamr@2: #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG) williamr@2: // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it williamr@2: operator bool () const { return !this->empty(); } williamr@2: #else williamr@2: private: williamr@2: struct dummy { williamr@2: void nonnull() {}; williamr@2: }; williamr@2: williamr@2: typedef void (dummy::*safe_bool)(); williamr@2: williamr@2: public: williamr@2: operator safe_bool () const williamr@2: { return (this->empty())? 0 : &dummy::nonnull; } williamr@2: williamr@2: bool operator!() const williamr@2: { return this->empty(); } williamr@2: #endif williamr@2: williamr@2: private: williamr@2: void assign_to_own(const BOOST_FUNCTION_FUNCTION& f) williamr@2: { williamr@2: if (!f.empty()) { williamr@2: this->vtable = f.vtable; williamr@2: f.vtable->manager(f.functor, this->functor, williamr@2: boost::detail::function::clone_functor_tag); williamr@2: } williamr@2: } williamr@2: williamr@2: template williamr@2: void assign_to(Functor f) williamr@2: { williamr@2: static vtable_type stored_vtable(f); williamr@2: if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable; williamr@2: else vtable = 0; williamr@2: } williamr@2: }; williamr@2: williamr@2: template williamr@2: inline void swap(BOOST_FUNCTION_FUNCTION< williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS , williamr@2: Allocator williamr@2: >& f1, williamr@2: BOOST_FUNCTION_FUNCTION< williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS, williamr@2: Allocator williamr@2: >& f2) williamr@2: { williamr@2: f1.swap(f2); williamr@2: } williamr@2: williamr@2: #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300) williamr@2: template williamr@2: typename BOOST_FUNCTION_FUNCTION< williamr@2: R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, williamr@2: Allocator>::result_type williamr@2: BOOST_FUNCTION_FUNCTION williamr@2: ::operator()(BOOST_FUNCTION_PARMS) const williamr@2: { williamr@2: if (this->empty()) williamr@2: boost::throw_exception(bad_function_call()); williamr@2: williamr@2: return static_cast(vtable)->invoker williamr@2: (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); williamr@2: } williamr@2: #endif williamr@2: williamr@2: // Poison comparisons between boost::function objects of the same type. williamr@2: template williamr@2: void operator==(const BOOST_FUNCTION_FUNCTION< williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS , williamr@2: Allocator>&, williamr@2: const BOOST_FUNCTION_FUNCTION< williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS , williamr@2: Allocator>&); williamr@2: template williamr@2: void operator!=(const BOOST_FUNCTION_FUNCTION< williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS , williamr@2: Allocator>&, williamr@2: const BOOST_FUNCTION_FUNCTION< williamr@2: R BOOST_FUNCTION_COMMA williamr@2: BOOST_FUNCTION_TEMPLATE_ARGS , williamr@2: Allocator>&); williamr@2: williamr@2: #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) williamr@2: williamr@2: #if BOOST_FUNCTION_NUM_ARGS == 0 williamr@2: #define BOOST_FUNCTION_PARTIAL_SPEC R (void) williamr@2: #else williamr@2: #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)) williamr@2: #endif williamr@2: williamr@2: template williamr@2: class function williamr@2: : public BOOST_FUNCTION_FUNCTION williamr@2: { williamr@2: typedef BOOST_FUNCTION_FUNCTION base_type; williamr@2: typedef function self_type; williamr@2: williamr@2: struct clear_type {}; williamr@2: williamr@2: public: williamr@2: typedef typename base_type::allocator_type allocator_type; williamr@2: williamr@2: function() : base_type() {} williamr@2: williamr@2: template williamr@2: function(Functor f williamr@2: #ifndef BOOST_NO_SFINAE williamr@2: ,typename enable_if_c< williamr@2: (boost::type_traits::ice_not< williamr@2: (is_integral::value)>::value), williamr@2: int>::type = 0 williamr@2: #endif williamr@2: ) : williamr@2: base_type(f) williamr@2: { williamr@2: } williamr@2: williamr@2: #ifndef BOOST_NO_SFINAE williamr@2: function(clear_type*) : base_type() {} williamr@2: #endif williamr@2: williamr@2: function(const self_type& f) : base_type(static_cast(f)){} williamr@2: williamr@2: function(const base_type& f) : base_type(static_cast(f)){} williamr@2: williamr@2: self_type& operator=(const self_type& f) williamr@2: { williamr@2: self_type(f).swap(*this); williamr@2: return *this; williamr@2: } williamr@2: williamr@2: template williamr@2: #ifndef BOOST_NO_SFINAE williamr@2: typename enable_if_c< williamr@2: (boost::type_traits::ice_not< williamr@2: (is_integral::value)>::value), williamr@2: self_type&>::type williamr@2: #else williamr@2: self_type& williamr@2: #endif williamr@2: operator=(Functor f) williamr@2: { williamr@2: self_type(f).swap(*this); williamr@2: return *this; williamr@2: } williamr@2: williamr@2: #ifndef BOOST_NO_SFINAE williamr@2: self_type& operator=(clear_type*) williamr@2: { williamr@2: this->clear(); williamr@2: return *this; williamr@2: } williamr@2: #endif williamr@2: williamr@2: self_type& operator=(const base_type& f) williamr@2: { williamr@2: self_type(f).swap(*this); williamr@2: return *this; williamr@2: } williamr@2: }; williamr@2: williamr@2: #ifdef BOOST_MSVC williamr@2: # pragma warning(pop) williamr@2: #endif williamr@2: williamr@2: #undef BOOST_FUNCTION_PARTIAL_SPEC williamr@2: #endif // have partial specialization williamr@2: williamr@2: } // end namespace boost williamr@2: williamr@2: #ifdef BOOST_MSVC williamr@2: # pragma warning(pop) williamr@2: #endif williamr@2: williamr@2: // Cleanup after ourselves... williamr@2: #undef BOOST_FUNCTION_VTABLE williamr@2: #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR williamr@2: #undef BOOST_FUNCTION_COMMA williamr@2: #undef BOOST_FUNCTION_FUNCTION williamr@2: #undef BOOST_FUNCTION_FUNCTION_INVOKER williamr@2: #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER williamr@2: #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER williamr@2: #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER williamr@2: #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER williamr@2: #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER williamr@2: #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER williamr@2: #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER williamr@2: #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER williamr@2: #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER williamr@2: #undef BOOST_FUNCTION_TEMPLATE_PARMS williamr@2: #undef BOOST_FUNCTION_TEMPLATE_ARGS williamr@2: #undef BOOST_FUNCTION_PARMS williamr@2: #undef BOOST_FUNCTION_PARM williamr@2: #undef BOOST_FUNCTION_ARGS williamr@2: #undef BOOST_FUNCTION_ARG_TYPE williamr@2: #undef BOOST_FUNCTION_ARG_TYPES williamr@2: #undef BOOST_FUNCTION_VOID_RETURN_TYPE williamr@2: #undef BOOST_FUNCTION_RETURN