1 // Boost.Function library
3 // Copyright Douglas Gregor 2001-2006
4 // Copyright Emil Dotchevski 2007
5 // Use, modification and distribution is subject to the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
9 // For more information, see http://www.boost.org
11 // Note: this header is a header template and must NOT have multiple-inclusion
13 #include <boost/function/detail/prologue.hpp>
14 #include <boost/detail/no_exceptions_support.hpp>
16 #if defined(BOOST_MSVC)
17 # pragma warning( push )
18 # pragma warning( disable : 4127 ) // "conditional expression is constant"
21 #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
23 #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
25 #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
27 #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
29 #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
31 #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
32 typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
34 #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
36 // Comma if nonzero number of arguments
37 #if BOOST_FUNCTION_NUM_ARGS == 0
38 # define BOOST_FUNCTION_COMMA
40 # define BOOST_FUNCTION_COMMA ,
41 #endif // BOOST_FUNCTION_NUM_ARGS > 0
43 // Class names used in this version of the code
44 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
45 #define BOOST_FUNCTION_FUNCTION_INVOKER \
46 BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
47 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
48 BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
49 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
50 BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
51 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
52 BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
53 #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
54 BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
55 #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
56 BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
57 #define BOOST_FUNCTION_MEMBER_INVOKER \
58 BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
59 #define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
60 BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
61 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
62 BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
63 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
64 BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
65 #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
66 BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
67 #define BOOST_FUNCTION_GET_MEMBER_INVOKER \
68 BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
69 #define BOOST_FUNCTION_GET_INVOKER \
70 BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
71 #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
73 #ifndef BOOST_NO_VOID_RETURNS
74 # define BOOST_FUNCTION_VOID_RETURN_TYPE void
75 # define BOOST_FUNCTION_RETURN(X) X
77 # define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable
78 # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
86 typename R BOOST_FUNCTION_COMMA
87 BOOST_FUNCTION_TEMPLATE_PARMS
89 struct BOOST_FUNCTION_FUNCTION_INVOKER
91 static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
94 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
95 return f(BOOST_FUNCTION_ARGS);
100 typename FunctionPtr,
101 typename R BOOST_FUNCTION_COMMA
102 BOOST_FUNCTION_TEMPLATE_PARMS
104 struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
106 static BOOST_FUNCTION_VOID_RETURN_TYPE
107 invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
108 BOOST_FUNCTION_PARMS)
111 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
112 BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
117 typename FunctionObj,
118 typename R BOOST_FUNCTION_COMMA
119 BOOST_FUNCTION_TEMPLATE_PARMS
121 struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
123 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
124 BOOST_FUNCTION_PARMS)
128 if (function_allows_small_object_optimization<FunctionObj>::value)
129 f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
131 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
132 return (*f)(BOOST_FUNCTION_ARGS);
137 typename FunctionObj,
138 typename R BOOST_FUNCTION_COMMA
139 BOOST_FUNCTION_TEMPLATE_PARMS
141 struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
143 static BOOST_FUNCTION_VOID_RETURN_TYPE
144 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
145 BOOST_FUNCTION_PARMS)
149 if (function_allows_small_object_optimization<FunctionObj>::value)
150 f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
152 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
153 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
158 typename FunctionObj,
159 typename R BOOST_FUNCTION_COMMA
160 BOOST_FUNCTION_TEMPLATE_PARMS
162 struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
164 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
165 BOOST_FUNCTION_PARMS)
169 reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
170 return (*f)(BOOST_FUNCTION_ARGS);
175 typename FunctionObj,
176 typename R BOOST_FUNCTION_COMMA
177 BOOST_FUNCTION_TEMPLATE_PARMS
179 struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
181 static BOOST_FUNCTION_VOID_RETURN_TYPE
182 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
183 BOOST_FUNCTION_PARMS)
187 reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
188 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
192 #if BOOST_FUNCTION_NUM_ARGS > 0
193 /* Handle invocation of member pointers. */
196 typename R BOOST_FUNCTION_COMMA
197 BOOST_FUNCTION_TEMPLATE_PARMS
199 struct BOOST_FUNCTION_MEMBER_INVOKER
201 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
202 BOOST_FUNCTION_PARMS)
206 reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
207 return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
213 typename R BOOST_FUNCTION_COMMA
214 BOOST_FUNCTION_TEMPLATE_PARMS
216 struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
218 static BOOST_FUNCTION_VOID_RETURN_TYPE
219 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
220 BOOST_FUNCTION_PARMS)
224 reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
225 BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
231 typename FunctionPtr,
232 typename R BOOST_FUNCTION_COMMA
233 BOOST_FUNCTION_TEMPLATE_PARMS
235 struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
237 typedef typename mpl::if_c<(is_void<R>::value),
238 BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
240 R BOOST_FUNCTION_COMMA
241 BOOST_FUNCTION_TEMPLATE_ARGS
243 BOOST_FUNCTION_FUNCTION_INVOKER<
245 R BOOST_FUNCTION_COMMA
246 BOOST_FUNCTION_TEMPLATE_ARGS
252 typename FunctionObj,
253 typename R BOOST_FUNCTION_COMMA
254 BOOST_FUNCTION_TEMPLATE_PARMS
256 struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
258 typedef typename mpl::if_c<(is_void<R>::value),
259 BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
261 R BOOST_FUNCTION_COMMA
262 BOOST_FUNCTION_TEMPLATE_ARGS
264 BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
266 R BOOST_FUNCTION_COMMA
267 BOOST_FUNCTION_TEMPLATE_ARGS
273 typename FunctionObj,
274 typename R BOOST_FUNCTION_COMMA
275 BOOST_FUNCTION_TEMPLATE_PARMS
277 struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
279 typedef typename mpl::if_c<(is_void<R>::value),
280 BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
282 R BOOST_FUNCTION_COMMA
283 BOOST_FUNCTION_TEMPLATE_ARGS
285 BOOST_FUNCTION_FUNCTION_REF_INVOKER<
287 R BOOST_FUNCTION_COMMA
288 BOOST_FUNCTION_TEMPLATE_ARGS
293 #if BOOST_FUNCTION_NUM_ARGS > 0
294 /* Retrieve the appropriate invoker for a member pointer. */
297 typename R BOOST_FUNCTION_COMMA
298 BOOST_FUNCTION_TEMPLATE_PARMS
300 struct BOOST_FUNCTION_GET_MEMBER_INVOKER
302 typedef typename mpl::if_c<(is_void<R>::value),
303 BOOST_FUNCTION_VOID_MEMBER_INVOKER<
305 R BOOST_FUNCTION_COMMA
306 BOOST_FUNCTION_TEMPLATE_ARGS
308 BOOST_FUNCTION_MEMBER_INVOKER<
310 R BOOST_FUNCTION_COMMA
311 BOOST_FUNCTION_TEMPLATE_ARGS
317 /* Given the tag returned by get_function_tag, retrieve the
318 actual invoker that will be used for the given function
321 Each specialization contains an "apply" nested class template
322 that accepts the function object, return type, function
323 argument types, and allocator. The resulting "apply" class
324 contains two typedefs, "invoker_type" and "manager_type",
325 which correspond to the invoker and manager types. */
326 template<typename Tag>
327 struct BOOST_FUNCTION_GET_INVOKER { };
329 /* Retrieve the invoker for a function pointer. */
331 struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
333 template<typename FunctionPtr,
334 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
337 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
339 R BOOST_FUNCTION_COMMA
340 BOOST_FUNCTION_TEMPLATE_ARGS
344 typedef functor_manager<FunctionPtr> manager_type;
347 template<typename FunctionPtr,
348 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
352 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
354 R BOOST_FUNCTION_COMMA
355 BOOST_FUNCTION_TEMPLATE_ARGS
359 typedef functor_manager<FunctionPtr> manager_type;
363 #if BOOST_FUNCTION_NUM_ARGS > 0
364 /* Retrieve the invoker for a member pointer. */
366 struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
368 template<typename MemberPtr,
369 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
372 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
374 R BOOST_FUNCTION_COMMA
375 BOOST_FUNCTION_TEMPLATE_ARGS
379 typedef functor_manager<MemberPtr> manager_type;
382 template<typename MemberPtr,
383 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
387 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
389 R BOOST_FUNCTION_COMMA
390 BOOST_FUNCTION_TEMPLATE_ARGS
394 typedef functor_manager<MemberPtr> manager_type;
399 /* Retrieve the invoker for a function object. */
401 struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
403 template<typename FunctionObj,
404 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
407 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
409 R BOOST_FUNCTION_COMMA
410 BOOST_FUNCTION_TEMPLATE_ARGS
414 typedef functor_manager<FunctionObj> manager_type;
417 template<typename FunctionObj,
418 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
422 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
424 R BOOST_FUNCTION_COMMA
425 BOOST_FUNCTION_TEMPLATE_ARGS
429 typedef functor_manager_a<FunctionObj, Allocator> manager_type;
433 /* Retrieve the invoker for a reference to a function object. */
435 struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
437 template<typename RefWrapper,
438 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
441 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
442 typename RefWrapper::type,
443 R BOOST_FUNCTION_COMMA
444 BOOST_FUNCTION_TEMPLATE_ARGS
448 typedef reference_manager<typename RefWrapper::type> manager_type;
451 template<typename RefWrapper,
452 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
456 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
457 typename RefWrapper::type,
458 R BOOST_FUNCTION_COMMA
459 BOOST_FUNCTION_TEMPLATE_ARGS
463 typedef reference_manager<typename RefWrapper::type> manager_type;
469 * vtable for a specific boost::function instance. This
470 * structure must be an aggregate so that we can use static
471 * initialization in boost::function's assign_to and assign_to_a
472 * members. It therefore cannot have any constructors,
473 * destructors, base classes, etc.
475 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
476 struct BOOST_FUNCTION_VTABLE
478 #ifndef BOOST_NO_VOID_RETURNS
479 typedef R result_type;
481 typedef typename function_return_type<R>::type result_type;
482 #endif // BOOST_NO_VOID_RETURNS
484 typedef result_type (*invoker_type)(function_buffer&
486 BOOST_FUNCTION_TEMPLATE_ARGS);
489 bool assign_to(F f, function_buffer& functor) const
491 typedef typename get_function_tag<F>::type tag;
492 return assign_to(f, functor, tag());
494 template<typename F,typename Allocator>
495 bool assign_to_a(F f, function_buffer& functor, Allocator a) const
497 typedef typename get_function_tag<F>::type tag;
498 return assign_to_a(f, functor, a, tag());
501 void clear(function_buffer& functor) const
504 base.manager(functor, functor, destroy_functor_tag);
509 template<typename FunctionPtr>
511 assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
513 this->clear(functor);
515 // should be a reinterpret cast, but some compilers insist
516 // on giving cv-qualifiers to free functions
517 functor.func_ptr = reinterpret_cast<void (*)()>(f);
523 template<typename FunctionPtr,typename Allocator>
525 assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
527 return assign_to(f,functor,function_ptr_tag());
531 #if BOOST_FUNCTION_NUM_ARGS > 0
532 template<typename MemberPtr>
533 bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
535 // DPG TBD: Add explicit support for member function
536 // objects, so we invoke through mem_fn() but we retain the
537 // right target_type() values.
539 this->assign_to(boost::mem_fn(f), functor);
545 template<typename MemberPtr,typename Allocator>
546 bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const
548 // DPG TBD: Add explicit support for member function
549 // objects, so we invoke through mem_fn() but we retain the
550 // right target_type() values.
552 this->assign_to_a(boost::mem_fn(f), functor, a);
558 #endif // BOOST_FUNCTION_NUM_ARGS > 0
561 // Assign to a function object using the small object optimization
562 template<typename FunctionObj>
564 assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
566 new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f);
568 template<typename FunctionObj,typename Allocator>
570 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const
572 assign_functor(f,functor,mpl::true_());
575 // Assign to a function object allocated on the heap.
576 template<typename FunctionObj>
578 assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
580 functor.obj_ptr = new FunctionObj(f);
582 template<typename FunctionObj,typename Allocator>
584 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const
586 typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
587 typedef typename Allocator::template rebind<functor_wrapper_type>::other
588 wrapper_allocator_type;
589 typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
590 wrapper_allocator_type wrapper_allocator(a);
591 wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
592 wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
593 functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
594 functor.obj_ptr = new_f;
597 template<typename FunctionObj>
599 assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
601 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
602 assign_functor(f, functor,
603 mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
609 template<typename FunctionObj,typename Allocator>
611 assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
613 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
614 assign_functor_a(f, functor, a,
615 mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
622 // Reference to a function object
623 template<typename FunctionObj>
625 assign_to(const reference_wrapper<FunctionObj>& f,
626 function_buffer& functor, function_obj_ref_tag) const
628 functor.obj_ref.obj_ptr = (void *)(f.get_pointer());
629 functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
630 functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
633 template<typename FunctionObj,typename Allocator>
635 assign_to_a(const reference_wrapper<FunctionObj>& f,
636 function_buffer& functor, Allocator, function_obj_ref_tag) const
638 return assign_to(f,functor,function_obj_ref_tag());
643 invoker_type invoker;
645 } // end namespace function
646 } // end namespace detail
649 typename R BOOST_FUNCTION_COMMA
650 BOOST_FUNCTION_TEMPLATE_PARMS
652 class BOOST_FUNCTION_FUNCTION : public function_base
654 #if BOOST_FUNCTION_NUM_ARGS == 1
656 , public std::unary_function<T0,R>
658 #elif BOOST_FUNCTION_NUM_ARGS == 2
660 , public std::binary_function<T0,T1,R>
666 #ifndef BOOST_NO_VOID_RETURNS
667 typedef R result_type;
669 typedef typename boost::detail::function::function_return_type<R>::type
671 #endif // BOOST_NO_VOID_RETURNS
674 typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
675 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
678 vtable_type* get_vtable() const {
679 return reinterpret_cast<vtable_type*>(
680 reinterpret_cast<std::size_t>(vtable) & ~static_cast<size_t>(0x01));
683 struct clear_type {};
686 BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
688 // add signature for boost::lambda
689 template<typename Args>
692 typedef result_type type;
695 #if BOOST_FUNCTION_NUM_ARGS == 1
696 typedef T0 argument_type;
697 #elif BOOST_FUNCTION_NUM_ARGS == 2
698 typedef T0 first_argument_type;
699 typedef T1 second_argument_type;
702 BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
703 BOOST_FUNCTION_ARG_TYPES
705 typedef BOOST_FUNCTION_FUNCTION self_type;
707 BOOST_FUNCTION_FUNCTION() : function_base() { }
709 // MSVC chokes if the following two constructors are collapsed into
710 // one with a default parameter.
711 template<typename Functor>
712 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
713 #ifndef BOOST_NO_SFINAE
714 ,typename enable_if_c<
715 (boost::type_traits::ice_not<
716 (is_integral<Functor>::value)>::value),
718 #endif // BOOST_NO_SFINAE
724 template<typename Functor,typename Allocator>
725 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
726 #ifndef BOOST_NO_SFINAE
727 ,typename enable_if_c<
728 (boost::type_traits::ice_not<
729 (is_integral<Functor>::value)>::value),
731 #endif // BOOST_NO_SFINAE
735 this->assign_to_a(f,a);
738 #ifndef BOOST_NO_SFINAE
739 BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
741 BOOST_FUNCTION_FUNCTION(int zero) : function_base()
743 BOOST_ASSERT(zero == 0);
747 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
749 this->assign_to_own(f);
752 ~BOOST_FUNCTION_FUNCTION() { clear(); }
754 result_type operator()(BOOST_FUNCTION_PARMS) const
757 boost::throw_exception(bad_function_call());
759 return get_vtable()->invoker
760 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
763 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
764 // when to use self_type is obnoxious. MSVC cannot handle self_type as
765 // the return type of these assignment operators, but Borland C++ cannot
766 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
768 template<typename Functor>
769 #ifndef BOOST_NO_SFINAE
770 typename enable_if_c<
771 (boost::type_traits::ice_not<
772 (is_integral<Functor>::value)>::value),
773 BOOST_FUNCTION_FUNCTION&>::type
775 BOOST_FUNCTION_FUNCTION&
777 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
782 } BOOST_CATCH (...) {
789 template<typename Functor,typename Allocator>
790 void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
794 this->assign_to_a(f,a);
795 } BOOST_CATCH (...) {
802 #ifndef BOOST_NO_SFINAE
803 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
809 BOOST_FUNCTION_FUNCTION& operator=(int zero)
811 BOOST_ASSERT(zero == 0);
817 // Assignment from another BOOST_FUNCTION_FUNCTION
818 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
825 this->assign_to_own(f);
826 } BOOST_CATCH (...) {
834 void swap(BOOST_FUNCTION_FUNCTION& other)
839 BOOST_FUNCTION_FUNCTION tmp;
840 tmp.move_assign(*this);
841 this->move_assign(other);
842 other.move_assign(tmp);
845 // Clear out a target, if there is one
849 if (!this->has_trivial_copy_and_destroy())
850 get_vtable()->clear(this->functor);
855 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
856 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
857 operator bool () const { return !this->empty(); }
864 typedef void (dummy::*safe_bool)();
867 operator safe_bool () const
868 { return (this->empty())? 0 : &dummy::nonnull; }
870 bool operator!() const
871 { return this->empty(); }
875 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
878 this->vtable = f.vtable;
879 if (this->has_trivial_copy_and_destroy())
880 this->functor = f.functor;
882 get_vtable()->base.manager(f.functor, this->functor,
883 boost::detail::function::clone_functor_tag);
887 template<typename Functor>
888 void assign_to(Functor f)
890 using detail::function::vtable_base;
892 typedef typename detail::function::get_function_tag<Functor>::type tag;
893 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
894 typedef typename get_invoker::
895 template apply<Functor, R BOOST_FUNCTION_COMMA
896 BOOST_FUNCTION_TEMPLATE_ARGS>
899 typedef typename handler_type::invoker_type invoker_type;
900 typedef typename handler_type::manager_type manager_type;
902 // Note: it is extremely important that this initialization use
903 // static initialization. Otherwise, we will have a race
904 // condition here in multi-threaded code. See
905 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
906 static const vtable_type stored_vtable =
907 { { &manager_type::manage }, &invoker_type::invoke };
909 if (stored_vtable.assign_to(f, functor)) {
910 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
911 if (boost::has_trivial_copy_constructor<Functor>::value &&
912 boost::has_trivial_destructor<Functor>::value &&
913 detail::function::function_allows_small_object_optimization<Functor>::value)
914 value |= static_cast<size_t>(0x01);
915 vtable = reinterpret_cast<detail::function::vtable_base *>(value);
920 template<typename Functor,typename Allocator>
921 void assign_to_a(Functor f,Allocator a)
923 using detail::function::vtable_base;
925 typedef typename detail::function::get_function_tag<Functor>::type tag;
926 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
927 typedef typename get_invoker::
928 template apply_a<Functor, R BOOST_FUNCTION_COMMA
929 BOOST_FUNCTION_TEMPLATE_ARGS,
933 typedef typename handler_type::invoker_type invoker_type;
934 typedef typename handler_type::manager_type manager_type;
936 // Note: it is extremely important that this initialization use
937 // static initialization. Otherwise, we will have a race
938 // condition here in multi-threaded code. See
939 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
940 static const vtable_type stored_vtable =
941 { { &manager_type::manage }, &invoker_type::invoke };
943 if (stored_vtable.assign_to_a(f, functor, a)) {
944 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
945 if (boost::has_trivial_copy_constructor<Functor>::value &&
946 boost::has_trivial_destructor<Functor>::value &&
947 detail::function::function_allows_small_object_optimization<Functor>::value)
948 value |= static_cast<std::size_t>(0x01);
949 vtable = reinterpret_cast<detail::function::vtable_base *>(value);
954 // Moves the value from the specified argument to *this. If the argument
955 // has its function object allocated on the heap, move_assign will pass
956 // its buffer to *this, and set the argument's buffer pointer to NULL.
957 void move_assign(BOOST_FUNCTION_FUNCTION& f)
964 this->vtable = f.vtable;
965 if (this->has_trivial_copy_and_destroy())
966 this->functor = f.functor;
968 get_vtable()->base.manager(f.functor, this->functor,
969 boost::detail::function::move_functor_tag);
974 } BOOST_CATCH (...) {
982 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
983 inline void swap(BOOST_FUNCTION_FUNCTION<
984 R BOOST_FUNCTION_COMMA
985 BOOST_FUNCTION_TEMPLATE_ARGS
987 BOOST_FUNCTION_FUNCTION<
988 R BOOST_FUNCTION_COMMA
989 BOOST_FUNCTION_TEMPLATE_ARGS
995 // Poison comparisons between boost::function objects of the same type.
996 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
997 void operator==(const BOOST_FUNCTION_FUNCTION<
998 R BOOST_FUNCTION_COMMA
999 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1000 const BOOST_FUNCTION_FUNCTION<
1001 R BOOST_FUNCTION_COMMA
1002 BOOST_FUNCTION_TEMPLATE_ARGS>&);
1003 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1004 void operator!=(const BOOST_FUNCTION_FUNCTION<
1005 R BOOST_FUNCTION_COMMA
1006 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1007 const BOOST_FUNCTION_FUNCTION<
1008 R BOOST_FUNCTION_COMMA
1009 BOOST_FUNCTION_TEMPLATE_ARGS>& );
1011 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1013 #if BOOST_FUNCTION_NUM_ARGS == 0
1014 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
1016 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
1019 template<typename R BOOST_FUNCTION_COMMA
1020 BOOST_FUNCTION_TEMPLATE_PARMS>
1021 class function<BOOST_FUNCTION_PARTIAL_SPEC>
1022 : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1024 typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
1025 typedef function self_type;
1027 struct clear_type {};
1031 function() : base_type() {}
1033 template<typename Functor>
1035 #ifndef BOOST_NO_SFINAE
1036 ,typename enable_if_c<
1037 (boost::type_traits::ice_not<
1038 (is_integral<Functor>::value)>::value),
1045 template<typename Functor,typename Allocator>
1046 function(Functor f, Allocator a
1047 #ifndef BOOST_NO_SFINAE
1048 ,typename enable_if_c<
1049 (boost::type_traits::ice_not<
1050 (is_integral<Functor>::value)>::value),
1058 #ifndef BOOST_NO_SFINAE
1059 function(clear_type*) : base_type() {}
1062 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1064 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1066 self_type& operator=(const self_type& f)
1068 self_type(f).swap(*this);
1072 template<typename Functor>
1073 #ifndef BOOST_NO_SFINAE
1074 typename enable_if_c<
1075 (boost::type_traits::ice_not<
1076 (is_integral<Functor>::value)>::value),
1081 operator=(Functor f)
1083 self_type(f).swap(*this);
1087 #ifndef BOOST_NO_SFINAE
1088 self_type& operator=(clear_type*)
1095 self_type& operator=(const base_type& f)
1097 self_type(f).swap(*this);
1102 #undef BOOST_FUNCTION_PARTIAL_SPEC
1103 #endif // have partial specialization
1105 } // end namespace boost
1107 // Cleanup after ourselves...
1108 #undef BOOST_FUNCTION_VTABLE
1109 #undef BOOST_FUNCTION_COMMA
1110 #undef BOOST_FUNCTION_FUNCTION
1111 #undef BOOST_FUNCTION_FUNCTION_INVOKER
1112 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
1113 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
1114 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
1115 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
1116 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
1117 #undef BOOST_FUNCTION_MEMBER_INVOKER
1118 #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
1119 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
1120 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
1121 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
1122 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
1123 #undef BOOST_FUNCTION_GET_INVOKER
1124 #undef BOOST_FUNCTION_TEMPLATE_PARMS
1125 #undef BOOST_FUNCTION_TEMPLATE_ARGS
1126 #undef BOOST_FUNCTION_PARMS
1127 #undef BOOST_FUNCTION_PARM
1128 #undef BOOST_FUNCTION_ARGS
1129 #undef BOOST_FUNCTION_ARG_TYPE
1130 #undef BOOST_FUNCTION_ARG_TYPES
1131 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
1132 #undef BOOST_FUNCTION_RETURN
1134 #if defined(BOOST_MSVC)
1135 # pragma warning( pop )