| // Boost.Function library |
| |
| // Copyright Douglas Gregor 2001-2006 |
| // Copyright Emil Dotchevski 2007 |
| // Use, modification and distribution is subject to the Boost Software License, Version 1.0. |
| // (See accompanying file LICENSE_1_0.txt or copy at |
| // http://www.boost.org/LICENSE_1_0.txt) |
| |
| // For more information, see http://www.boost.org |
| |
| // Note: this header is a header template and must NOT have multiple-inclusion |
| // protection. |
| #include <ndnboost/function/detail/prologue.hpp> |
| #include <ndnboost/detail/no_exceptions_support.hpp> |
| |
| #if defined(BOOST_MSVC) |
| # pragma warning( push ) |
| # pragma warning( disable : 4127 ) // "conditional expression is constant" |
| #endif |
| |
| #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T) |
| |
| #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T) |
| |
| #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I) |
| |
| #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY) |
| |
| #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a) |
| |
| #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \ |
| typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type); |
| |
| #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY) |
| |
| // Comma if nonzero number of arguments |
| #if BOOST_FUNCTION_NUM_ARGS == 0 |
| # define BOOST_FUNCTION_COMMA |
| #else |
| # define BOOST_FUNCTION_COMMA , |
| #endif // BOOST_FUNCTION_NUM_ARGS > 0 |
| |
| // Class names used in this version of the code |
| #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_FUNCTION_INVOKER \ |
| BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \ |
| BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \ |
| BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \ |
| BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \ |
| BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \ |
| BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_MEMBER_INVOKER \ |
| BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_VOID_MEMBER_INVOKER \ |
| BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \ |
| BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \ |
| BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \ |
| BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_GET_MEMBER_INVOKER \ |
| BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_GET_INVOKER \ |
| BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS) |
| #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS) |
| |
| #ifndef BOOST_NO_VOID_RETURNS |
| # define BOOST_FUNCTION_VOID_RETURN_TYPE void |
| # define BOOST_FUNCTION_RETURN(X) X |
| #else |
| # define BOOST_FUNCTION_VOID_RETURN_TYPE ndnboost::detail::function::unusable |
| # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE () |
| #endif |
| |
| namespace ndnboost { |
| namespace detail { |
| namespace function { |
| template< |
| typename FunctionPtr, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_FUNCTION_INVOKER |
| { |
| static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_PARMS) |
| { |
| FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); |
| return f(BOOST_FUNCTION_ARGS); |
| } |
| }; |
| |
| template< |
| typename FunctionPtr, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER |
| { |
| static BOOST_FUNCTION_VOID_RETURN_TYPE |
| invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_PARMS) |
| |
| { |
| FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); |
| BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS)); |
| } |
| }; |
| |
| template< |
| typename FunctionObj, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER |
| { |
| static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_PARMS) |
| |
| { |
| FunctionObj* f; |
| if (function_allows_small_object_optimization<FunctionObj>::value) |
| f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data); |
| else |
| f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); |
| return (*f)(BOOST_FUNCTION_ARGS); |
| } |
| }; |
| |
| template< |
| typename FunctionObj, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER |
| { |
| static BOOST_FUNCTION_VOID_RETURN_TYPE |
| invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_PARMS) |
| |
| { |
| FunctionObj* f; |
| if (function_allows_small_object_optimization<FunctionObj>::value) |
| f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data); |
| else |
| f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); |
| BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); |
| } |
| }; |
| |
| template< |
| typename FunctionObj, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_FUNCTION_REF_INVOKER |
| { |
| static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_PARMS) |
| |
| { |
| FunctionObj* f = |
| reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); |
| return (*f)(BOOST_FUNCTION_ARGS); |
| } |
| }; |
| |
| template< |
| typename FunctionObj, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER |
| { |
| static BOOST_FUNCTION_VOID_RETURN_TYPE |
| invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_PARMS) |
| |
| { |
| FunctionObj* f = |
| reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); |
| BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); |
| } |
| }; |
| |
| #if BOOST_FUNCTION_NUM_ARGS > 0 |
| /* Handle invocation of member pointers. */ |
| template< |
| typename MemberPtr, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_MEMBER_INVOKER |
| { |
| static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_PARMS) |
| |
| { |
| MemberPtr* f = |
| reinterpret_cast<MemberPtr*>(&function_obj_ptr.data); |
| return ndnboost::mem_fn(*f)(BOOST_FUNCTION_ARGS); |
| } |
| }; |
| |
| template< |
| typename MemberPtr, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_VOID_MEMBER_INVOKER |
| { |
| static BOOST_FUNCTION_VOID_RETURN_TYPE |
| invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_PARMS) |
| |
| { |
| MemberPtr* f = |
| reinterpret_cast<MemberPtr*>(&function_obj_ptr.data); |
| BOOST_FUNCTION_RETURN(ndnboost::mem_fn(*f)(BOOST_FUNCTION_ARGS)); |
| } |
| }; |
| #endif |
| |
| template< |
| typename FunctionPtr, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_GET_FUNCTION_INVOKER |
| { |
| typedef typename mpl::if_c<(is_void<R>::value), |
| BOOST_FUNCTION_VOID_FUNCTION_INVOKER< |
| FunctionPtr, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >, |
| BOOST_FUNCTION_FUNCTION_INVOKER< |
| FunctionPtr, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| > |
| >::type type; |
| }; |
| |
| template< |
| typename FunctionObj, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER |
| { |
| typedef typename mpl::if_c<(is_void<R>::value), |
| BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER< |
| FunctionObj, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >, |
| BOOST_FUNCTION_FUNCTION_OBJ_INVOKER< |
| FunctionObj, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| > |
| >::type type; |
| }; |
| |
| template< |
| typename FunctionObj, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER |
| { |
| typedef typename mpl::if_c<(is_void<R>::value), |
| BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER< |
| FunctionObj, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >, |
| BOOST_FUNCTION_FUNCTION_REF_INVOKER< |
| FunctionObj, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| > |
| >::type type; |
| }; |
| |
| #if BOOST_FUNCTION_NUM_ARGS > 0 |
| /* Retrieve the appropriate invoker for a member pointer. */ |
| template< |
| typename MemberPtr, |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| struct BOOST_FUNCTION_GET_MEMBER_INVOKER |
| { |
| typedef typename mpl::if_c<(is_void<R>::value), |
| BOOST_FUNCTION_VOID_MEMBER_INVOKER< |
| MemberPtr, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >, |
| BOOST_FUNCTION_MEMBER_INVOKER< |
| MemberPtr, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| > |
| >::type type; |
| }; |
| #endif |
| |
| /* Given the tag returned by get_function_tag, retrieve the |
| actual invoker that will be used for the given function |
| object. |
| |
| Each specialization contains an "apply" nested class template |
| that accepts the function object, return type, function |
| argument types, and allocator. The resulting "apply" class |
| contains two typedefs, "invoker_type" and "manager_type", |
| which correspond to the invoker and manager types. */ |
| template<typename Tag> |
| struct BOOST_FUNCTION_GET_INVOKER { }; |
| |
| /* Retrieve the invoker for a function pointer. */ |
| template<> |
| struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag> |
| { |
| template<typename FunctionPtr, |
| typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> |
| struct apply |
| { |
| typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< |
| FunctionPtr, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >::type |
| invoker_type; |
| |
| typedef functor_manager<FunctionPtr> manager_type; |
| }; |
| |
| template<typename FunctionPtr, |
| typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, |
| typename Allocator> |
| struct apply_a |
| { |
| typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER< |
| FunctionPtr, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >::type |
| invoker_type; |
| |
| typedef functor_manager<FunctionPtr> manager_type; |
| }; |
| }; |
| |
| #if BOOST_FUNCTION_NUM_ARGS > 0 |
| /* Retrieve the invoker for a member pointer. */ |
| template<> |
| struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag> |
| { |
| template<typename MemberPtr, |
| typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> |
| struct apply |
| { |
| typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER< |
| MemberPtr, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >::type |
| invoker_type; |
| |
| typedef functor_manager<MemberPtr> manager_type; |
| }; |
| |
| template<typename MemberPtr, |
| typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, |
| typename Allocator> |
| struct apply_a |
| { |
| typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER< |
| MemberPtr, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >::type |
| invoker_type; |
| |
| typedef functor_manager<MemberPtr> manager_type; |
| }; |
| }; |
| #endif |
| |
| /* Retrieve the invoker for a function object. */ |
| template<> |
| struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag> |
| { |
| template<typename FunctionObj, |
| typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> |
| struct apply |
| { |
| typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< |
| FunctionObj, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >::type |
| invoker_type; |
| |
| typedef functor_manager<FunctionObj> manager_type; |
| }; |
| |
| template<typename FunctionObj, |
| typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, |
| typename Allocator> |
| struct apply_a |
| { |
| typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER< |
| FunctionObj, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >::type |
| invoker_type; |
| |
| typedef functor_manager_a<FunctionObj, Allocator> manager_type; |
| }; |
| }; |
| |
| /* Retrieve the invoker for a reference to a function object. */ |
| template<> |
| struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag> |
| { |
| template<typename RefWrapper, |
| typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> |
| struct apply |
| { |
| typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< |
| typename RefWrapper::type, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >::type |
| invoker_type; |
| |
| typedef reference_manager<typename RefWrapper::type> manager_type; |
| }; |
| |
| template<typename RefWrapper, |
| typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, |
| typename Allocator> |
| struct apply_a |
| { |
| typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER< |
| typename RefWrapper::type, |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >::type |
| invoker_type; |
| |
| typedef reference_manager<typename RefWrapper::type> manager_type; |
| }; |
| }; |
| |
| |
| /** |
| * vtable for a specific ndnboost::function instance. This |
| * structure must be an aggregate so that we can use static |
| * initialization in ndnboost::function's assign_to and assign_to_a |
| * members. It therefore cannot have any constructors, |
| * destructors, base classes, etc. |
| */ |
| template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> |
| struct BOOST_FUNCTION_VTABLE |
| { |
| #ifndef BOOST_NO_VOID_RETURNS |
| typedef R result_type; |
| #else |
| typedef typename function_return_type<R>::type result_type; |
| #endif // BOOST_NO_VOID_RETURNS |
| |
| typedef result_type (*invoker_type)(function_buffer& |
| BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS); |
| |
| template<typename F> |
| bool assign_to(F f, function_buffer& functor) const |
| { |
| typedef typename get_function_tag<F>::type tag; |
| return assign_to(f, functor, tag()); |
| } |
| template<typename F,typename Allocator> |
| bool assign_to_a(F f, function_buffer& functor, Allocator a) const |
| { |
| typedef typename get_function_tag<F>::type tag; |
| return assign_to_a(f, functor, a, tag()); |
| } |
| |
| void clear(function_buffer& functor) const |
| { |
| if (base.manager) |
| base.manager(functor, functor, destroy_functor_tag); |
| } |
| |
| private: |
| // Function pointers |
| template<typename FunctionPtr> |
| bool |
| assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const |
| { |
| this->clear(functor); |
| if (f) { |
| // should be a reinterpret cast, but some compilers insist |
| // on giving cv-qualifiers to free functions |
| functor.func_ptr = reinterpret_cast<void (*)()>(f); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| template<typename FunctionPtr,typename Allocator> |
| bool |
| assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const |
| { |
| return assign_to(f,functor,function_ptr_tag()); |
| } |
| |
| // Member pointers |
| #if BOOST_FUNCTION_NUM_ARGS > 0 |
| template<typename MemberPtr> |
| bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const |
| { |
| // DPG TBD: Add explicit support for member function |
| // objects, so we invoke through mem_fn() but we retain the |
| // right target_type() values. |
| if (f) { |
| this->assign_to(ndnboost::mem_fn(f), functor); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| template<typename MemberPtr,typename Allocator> |
| bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const |
| { |
| // DPG TBD: Add explicit support for member function |
| // objects, so we invoke through mem_fn() but we retain the |
| // right target_type() values. |
| if (f) { |
| this->assign_to_a(ndnboost::mem_fn(f), functor, a); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| #endif // BOOST_FUNCTION_NUM_ARGS > 0 |
| |
| // Function objects |
| // Assign to a function object using the small object optimization |
| template<typename FunctionObj> |
| void |
| assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const |
| { |
| new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f); |
| } |
| template<typename FunctionObj,typename Allocator> |
| void |
| assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const |
| { |
| assign_functor(f,functor,mpl::true_()); |
| } |
| |
| // Assign to a function object allocated on the heap. |
| template<typename FunctionObj> |
| void |
| assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const |
| { |
| functor.obj_ptr = new FunctionObj(f); |
| } |
| template<typename FunctionObj,typename Allocator> |
| void |
| assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const |
| { |
| typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type; |
| typedef typename Allocator::template rebind<functor_wrapper_type>::other |
| wrapper_allocator_type; |
| typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type; |
| wrapper_allocator_type wrapper_allocator(a); |
| wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); |
| wrapper_allocator.construct(copy, functor_wrapper_type(f,a)); |
| functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); |
| functor.obj_ptr = new_f; |
| } |
| |
| template<typename FunctionObj> |
| bool |
| assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const |
| { |
| if (!ndnboost::detail::function::has_empty_target(ndnboost::addressof(f))) { |
| assign_functor(f, functor, |
| mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>()); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| template<typename FunctionObj,typename Allocator> |
| bool |
| assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const |
| { |
| if (!ndnboost::detail::function::has_empty_target(ndnboost::addressof(f))) { |
| assign_functor_a(f, functor, a, |
| mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>()); |
| return true; |
| } else { |
| return false; |
| } |
| } |
| |
| // Reference to a function object |
| template<typename FunctionObj> |
| bool |
| assign_to(const reference_wrapper<FunctionObj>& f, |
| function_buffer& functor, function_obj_ref_tag) const |
| { |
| functor.obj_ref.obj_ptr = (void *)(f.get_pointer()); |
| functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value; |
| functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value; |
| return true; |
| } |
| template<typename FunctionObj,typename Allocator> |
| bool |
| assign_to_a(const reference_wrapper<FunctionObj>& f, |
| function_buffer& functor, Allocator, function_obj_ref_tag) const |
| { |
| return assign_to(f,functor,function_obj_ref_tag()); |
| } |
| |
| public: |
| vtable_base base; |
| invoker_type invoker; |
| }; |
| } // end namespace function |
| } // end namespace detail |
| |
| template< |
| typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS |
| > |
| class BOOST_FUNCTION_FUNCTION : public function_base |
| |
| #if BOOST_FUNCTION_NUM_ARGS == 1 |
| |
| , public std::unary_function<T0,R> |
| |
| #elif BOOST_FUNCTION_NUM_ARGS == 2 |
| |
| , public std::binary_function<T0,T1,R> |
| |
| #endif |
| |
| { |
| public: |
| #ifndef BOOST_NO_VOID_RETURNS |
| typedef R result_type; |
| #else |
| typedef typename ndnboost::detail::function::function_return_type<R>::type |
| result_type; |
| #endif // BOOST_NO_VOID_RETURNS |
| |
| private: |
| typedef ndnboost::detail::function::BOOST_FUNCTION_VTABLE< |
| R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> |
| vtable_type; |
| |
| vtable_type* get_vtable() const { |
| return reinterpret_cast<vtable_type*>( |
| reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01)); |
| } |
| |
| struct clear_type {}; |
| |
| public: |
| BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); |
| |
| // add signature for ndnboost::lambda |
| template<typename Args> |
| struct sig |
| { |
| typedef result_type type; |
| }; |
| |
| #if BOOST_FUNCTION_NUM_ARGS == 1 |
| typedef T0 argument_type; |
| #elif BOOST_FUNCTION_NUM_ARGS == 2 |
| typedef T0 first_argument_type; |
| typedef T1 second_argument_type; |
| #endif |
| |
| BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS); |
| BOOST_FUNCTION_ARG_TYPES |
| |
| typedef BOOST_FUNCTION_FUNCTION self_type; |
| |
| BOOST_FUNCTION_FUNCTION() : function_base() { } |
| |
| // MSVC chokes if the following two constructors are collapsed into |
| // one with a default parameter. |
| template<typename Functor> |
| BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f |
| #ifndef BOOST_NO_SFINAE |
| ,typename enable_if_c< |
| (ndnboost::type_traits::ice_not< |
| (is_integral<Functor>::value)>::value), |
| int>::type = 0 |
| #endif // BOOST_NO_SFINAE |
| ) : |
| function_base() |
| { |
| this->assign_to(f); |
| } |
| template<typename Functor,typename Allocator> |
| BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a |
| #ifndef BOOST_NO_SFINAE |
| ,typename enable_if_c< |
| (ndnboost::type_traits::ice_not< |
| (is_integral<Functor>::value)>::value), |
| int>::type = 0 |
| #endif // BOOST_NO_SFINAE |
| ) : |
| function_base() |
| { |
| this->assign_to_a(f,a); |
| } |
| |
| #ifndef BOOST_NO_SFINAE |
| BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { } |
| #else |
| BOOST_FUNCTION_FUNCTION(int zero) : function_base() |
| { |
| BOOST_ASSERT(zero == 0); |
| } |
| #endif |
| |
| BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base() |
| { |
| this->assign_to_own(f); |
| } |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base() |
| { |
| this->move_assign(f); |
| } |
| #endif |
| |
| ~BOOST_FUNCTION_FUNCTION() { clear(); } |
| |
| result_type operator()(BOOST_FUNCTION_PARMS) const |
| { |
| if (this->empty()) |
| ndnboost::throw_exception(bad_function_call()); |
| |
| return get_vtable()->invoker |
| (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); |
| } |
| |
| // The distinction between when to use BOOST_FUNCTION_FUNCTION and |
| // when to use self_type is obnoxious. MSVC cannot handle self_type as |
| // the return type of these assignment operators, but Borland C++ cannot |
| // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to |
| // construct. |
| template<typename Functor> |
| #ifndef BOOST_NO_SFINAE |
| typename enable_if_c< |
| (ndnboost::type_traits::ice_not< |
| (is_integral<Functor>::value)>::value), |
| BOOST_FUNCTION_FUNCTION&>::type |
| #else |
| BOOST_FUNCTION_FUNCTION& |
| #endif |
| operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) |
| { |
| this->clear(); |
| BOOST_TRY { |
| this->assign_to(f); |
| } BOOST_CATCH (...) { |
| vtable = 0; |
| BOOST_RETHROW; |
| } |
| BOOST_CATCH_END |
| return *this; |
| } |
| template<typename Functor,typename Allocator> |
| void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a) |
| { |
| this->clear(); |
| BOOST_TRY{ |
| this->assign_to_a(f,a); |
| } BOOST_CATCH (...) { |
| vtable = 0; |
| BOOST_RETHROW; |
| } |
| BOOST_CATCH_END |
| } |
| |
| #ifndef BOOST_NO_SFINAE |
| BOOST_FUNCTION_FUNCTION& operator=(clear_type*) |
| { |
| this->clear(); |
| return *this; |
| } |
| #else |
| BOOST_FUNCTION_FUNCTION& operator=(int zero) |
| { |
| BOOST_ASSERT(zero == 0); |
| this->clear(); |
| return *this; |
| } |
| #endif |
| |
| // Assignment from another BOOST_FUNCTION_FUNCTION |
| BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) |
| { |
| if (&f == this) |
| return *this; |
| |
| this->clear(); |
| BOOST_TRY { |
| this->assign_to_own(f); |
| } BOOST_CATCH (...) { |
| vtable = 0; |
| BOOST_RETHROW; |
| } |
| BOOST_CATCH_END |
| return *this; |
| } |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| // Move assignment from another BOOST_FUNCTION_FUNCTION |
| BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f) |
| { |
| |
| if (&f == this) |
| return *this; |
| |
| this->clear(); |
| BOOST_TRY { |
| this->move_assign(f); |
| } BOOST_CATCH (...) { |
| vtable = 0; |
| BOOST_RETHROW; |
| } |
| BOOST_CATCH_END |
| return *this; |
| } |
| #endif |
| |
| void swap(BOOST_FUNCTION_FUNCTION& other) |
| { |
| if (&other == this) |
| return; |
| |
| BOOST_FUNCTION_FUNCTION tmp; |
| tmp.move_assign(*this); |
| this->move_assign(other); |
| other.move_assign(tmp); |
| } |
| |
| // Clear out a target, if there is one |
| void clear() |
| { |
| if (vtable) { |
| if (!this->has_trivial_copy_and_destroy()) |
| get_vtable()->clear(this->functor); |
| vtable = 0; |
| } |
| } |
| |
| #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG) |
| // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it |
| operator bool () const { return !this->empty(); } |
| #else |
| private: |
| struct dummy { |
| void nonnull() {} |
| }; |
| |
| typedef void (dummy::*safe_bool)(); |
| |
| public: |
| operator safe_bool () const |
| { return (this->empty())? 0 : &dummy::nonnull; } |
| |
| bool operator!() const |
| { return this->empty(); } |
| #endif |
| |
| private: |
| void assign_to_own(const BOOST_FUNCTION_FUNCTION& f) |
| { |
| if (!f.empty()) { |
| this->vtable = f.vtable; |
| if (this->has_trivial_copy_and_destroy()) |
| this->functor = f.functor; |
| else |
| get_vtable()->base.manager(f.functor, this->functor, |
| ndnboost::detail::function::clone_functor_tag); |
| } |
| } |
| |
| template<typename Functor> |
| void assign_to(Functor f) |
| { |
| using detail::function::vtable_base; |
| |
| typedef typename detail::function::get_function_tag<Functor>::type tag; |
| typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; |
| typedef typename get_invoker:: |
| template apply<Functor, R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS> |
| handler_type; |
| |
| typedef typename handler_type::invoker_type invoker_type; |
| typedef typename handler_type::manager_type manager_type; |
| |
| // Note: it is extremely important that this initialization use |
| // static initialization. Otherwise, we will have a race |
| // condition here in multi-threaded code. See |
| // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/. |
| static const vtable_type stored_vtable = |
| { { &manager_type::manage }, &invoker_type::invoke }; |
| |
| if (stored_vtable.assign_to(f, functor)) { |
| std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base); |
| if (ndnboost::has_trivial_copy_constructor<Functor>::value && |
| ndnboost::has_trivial_destructor<Functor>::value && |
| detail::function::function_allows_small_object_optimization<Functor>::value) |
| value |= static_cast<size_t>(0x01); |
| vtable = reinterpret_cast<detail::function::vtable_base *>(value); |
| } else |
| vtable = 0; |
| } |
| |
| template<typename Functor,typename Allocator> |
| void assign_to_a(Functor f,Allocator a) |
| { |
| using detail::function::vtable_base; |
| |
| typedef typename detail::function::get_function_tag<Functor>::type tag; |
| typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; |
| typedef typename get_invoker:: |
| template apply_a<Functor, R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS, |
| Allocator> |
| handler_type; |
| |
| typedef typename handler_type::invoker_type invoker_type; |
| typedef typename handler_type::manager_type manager_type; |
| |
| // Note: it is extremely important that this initialization use |
| // static initialization. Otherwise, we will have a race |
| // condition here in multi-threaded code. See |
| // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/. |
| static const vtable_type stored_vtable = |
| { { &manager_type::manage }, &invoker_type::invoke }; |
| |
| if (stored_vtable.assign_to_a(f, functor, a)) { |
| std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base); |
| if (ndnboost::has_trivial_copy_constructor<Functor>::value && |
| ndnboost::has_trivial_destructor<Functor>::value && |
| detail::function::function_allows_small_object_optimization<Functor>::value) |
| value |= static_cast<std::size_t>(0x01); |
| vtable = reinterpret_cast<detail::function::vtable_base *>(value); |
| } else |
| vtable = 0; |
| } |
| |
| // Moves the value from the specified argument to *this. If the argument |
| // has its function object allocated on the heap, move_assign will pass |
| // its buffer to *this, and set the argument's buffer pointer to NULL. |
| void move_assign(BOOST_FUNCTION_FUNCTION& f) |
| { |
| if (&f == this) |
| return; |
| |
| BOOST_TRY { |
| if (!f.empty()) { |
| this->vtable = f.vtable; |
| if (this->has_trivial_copy_and_destroy()) |
| this->functor = f.functor; |
| else |
| get_vtable()->base.manager(f.functor, this->functor, |
| ndnboost::detail::function::move_functor_tag); |
| f.vtable = 0; |
| } else { |
| clear(); |
| } |
| } BOOST_CATCH (...) { |
| vtable = 0; |
| BOOST_RETHROW; |
| } |
| BOOST_CATCH_END |
| } |
| }; |
| |
| template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> |
| inline void swap(BOOST_FUNCTION_FUNCTION< |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >& f1, |
| BOOST_FUNCTION_FUNCTION< |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS |
| >& f2) |
| { |
| f1.swap(f2); |
| } |
| |
| // Poison comparisons between ndnboost::function objects of the same type. |
| template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> |
| void operator==(const BOOST_FUNCTION_FUNCTION< |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS>&, |
| const BOOST_FUNCTION_FUNCTION< |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS>&); |
| template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS> |
| void operator!=(const BOOST_FUNCTION_FUNCTION< |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS>&, |
| const BOOST_FUNCTION_FUNCTION< |
| R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_ARGS>& ); |
| |
| #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) |
| |
| #if BOOST_FUNCTION_NUM_ARGS == 0 |
| #define BOOST_FUNCTION_PARTIAL_SPEC R (void) |
| #else |
| #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)) |
| #endif |
| |
| template<typename R BOOST_FUNCTION_COMMA |
| BOOST_FUNCTION_TEMPLATE_PARMS> |
| class function<BOOST_FUNCTION_PARTIAL_SPEC> |
| : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> |
| { |
| typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type; |
| typedef function self_type; |
| |
| struct clear_type {}; |
| |
| public: |
| |
| function() : base_type() {} |
| |
| template<typename Functor> |
| function(Functor f |
| #ifndef BOOST_NO_SFINAE |
| ,typename enable_if_c< |
| (ndnboost::type_traits::ice_not< |
| (is_integral<Functor>::value)>::value), |
| int>::type = 0 |
| #endif |
| ) : |
| base_type(f) |
| { |
| } |
| template<typename Functor,typename Allocator> |
| function(Functor f, Allocator a |
| #ifndef BOOST_NO_SFINAE |
| ,typename enable_if_c< |
| (ndnboost::type_traits::ice_not< |
| (is_integral<Functor>::value)>::value), |
| int>::type = 0 |
| #endif |
| ) : |
| base_type(f,a) |
| { |
| } |
| |
| #ifndef BOOST_NO_SFINAE |
| function(clear_type*) : base_type() {} |
| #endif |
| |
| function(const self_type& f) : base_type(static_cast<const base_type&>(f)){} |
| |
| function(const base_type& f) : base_type(static_cast<const base_type&>(f)){} |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| // Move constructors |
| function(self_type&& f): base_type(static_cast<base_type&&>(f)){} |
| function(base_type&& f): base_type(static_cast<base_type&&>(f)){} |
| #endif |
| |
| self_type& operator=(const self_type& f) |
| { |
| self_type(f).swap(*this); |
| return *this; |
| } |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| self_type& operator=(self_type&& f) |
| { |
| self_type(static_cast<self_type&&>(f)).swap(*this); |
| return *this; |
| } |
| #endif |
| |
| template<typename Functor> |
| #ifndef BOOST_NO_SFINAE |
| typename enable_if_c< |
| (ndnboost::type_traits::ice_not< |
| (is_integral<Functor>::value)>::value), |
| self_type&>::type |
| #else |
| self_type& |
| #endif |
| operator=(Functor f) |
| { |
| self_type(f).swap(*this); |
| return *this; |
| } |
| |
| #ifndef BOOST_NO_SFINAE |
| self_type& operator=(clear_type*) |
| { |
| this->clear(); |
| return *this; |
| } |
| #endif |
| |
| self_type& operator=(const base_type& f) |
| { |
| self_type(f).swap(*this); |
| return *this; |
| } |
| |
| #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
| self_type& operator=(base_type&& f) |
| { |
| self_type(static_cast<base_type&&>(f)).swap(*this); |
| return *this; |
| } |
| #endif |
| }; |
| |
| #undef BOOST_FUNCTION_PARTIAL_SPEC |
| #endif // have partial specialization |
| |
| } // end namespace ndnboost |
| |
| // Cleanup after ourselves... |
| #undef BOOST_FUNCTION_VTABLE |
| #undef BOOST_FUNCTION_COMMA |
| #undef BOOST_FUNCTION_FUNCTION |
| #undef BOOST_FUNCTION_FUNCTION_INVOKER |
| #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER |
| #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER |
| #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER |
| #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER |
| #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER |
| #undef BOOST_FUNCTION_MEMBER_INVOKER |
| #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER |
| #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER |
| #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER |
| #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER |
| #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER |
| #undef BOOST_FUNCTION_GET_INVOKER |
| #undef BOOST_FUNCTION_TEMPLATE_PARMS |
| #undef BOOST_FUNCTION_TEMPLATE_ARGS |
| #undef BOOST_FUNCTION_PARMS |
| #undef BOOST_FUNCTION_PARM |
| #undef BOOST_FUNCTION_ARGS |
| #undef BOOST_FUNCTION_ARG_TYPE |
| #undef BOOST_FUNCTION_ARG_TYPES |
| #undef BOOST_FUNCTION_VOID_RETURN_TYPE |
| #undef BOOST_FUNCTION_RETURN |
| |
| #if defined(BOOST_MSVC) |
| # pragma warning( pop ) |
| #endif |