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