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<std::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 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
753 BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
755 this->move_assign(f);
759 ~BOOST_FUNCTION_FUNCTION() { clear(); }
761 result_type operator()(BOOST_FUNCTION_PARMS) const
764 boost::throw_exception(bad_function_call());
766 return get_vtable()->invoker
767 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
770 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
771 // when to use self_type is obnoxious. MSVC cannot handle self_type as
772 // the return type of these assignment operators, but Borland C++ cannot
773 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
775 template<typename Functor>
776 #ifndef BOOST_NO_SFINAE
777 typename enable_if_c<
778 (boost::type_traits::ice_not<
779 (is_integral<Functor>::value)>::value),
780 BOOST_FUNCTION_FUNCTION&>::type
782 BOOST_FUNCTION_FUNCTION&
784 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
789 } BOOST_CATCH (...) {
796 template<typename Functor,typename Allocator>
797 void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
801 this->assign_to_a(f,a);
802 } BOOST_CATCH (...) {
809 #ifndef BOOST_NO_SFINAE
810 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
816 BOOST_FUNCTION_FUNCTION& operator=(int zero)
818 BOOST_ASSERT(zero == 0);
824 // Assignment from another BOOST_FUNCTION_FUNCTION
825 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
832 this->assign_to_own(f);
833 } BOOST_CATCH (...) {
841 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
842 // Move assignment from another BOOST_FUNCTION_FUNCTION
843 BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
851 this->move_assign(f);
852 } BOOST_CATCH (...) {
861 void swap(BOOST_FUNCTION_FUNCTION& other)
866 BOOST_FUNCTION_FUNCTION tmp;
867 tmp.move_assign(*this);
868 this->move_assign(other);
869 other.move_assign(tmp);
872 // Clear out a target, if there is one
876 if (!this->has_trivial_copy_and_destroy())
877 get_vtable()->clear(this->functor);
882 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
883 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
884 operator bool () const { return !this->empty(); }
891 typedef void (dummy::*safe_bool)();
894 operator safe_bool () const
895 { return (this->empty())? 0 : &dummy::nonnull; }
897 bool operator!() const
898 { return this->empty(); }
902 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
905 this->vtable = f.vtable;
906 if (this->has_trivial_copy_and_destroy())
907 this->functor = f.functor;
909 get_vtable()->base.manager(f.functor, this->functor,
910 boost::detail::function::clone_functor_tag);
914 template<typename Functor>
915 void assign_to(Functor f)
917 using detail::function::vtable_base;
919 typedef typename detail::function::get_function_tag<Functor>::type tag;
920 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
921 typedef typename get_invoker::
922 template apply<Functor, R BOOST_FUNCTION_COMMA
923 BOOST_FUNCTION_TEMPLATE_ARGS>
926 typedef typename handler_type::invoker_type invoker_type;
927 typedef typename handler_type::manager_type manager_type;
929 // Note: it is extremely important that this initialization use
930 // static initialization. Otherwise, we will have a race
931 // condition here in multi-threaded code. See
932 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
933 static const vtable_type stored_vtable =
934 { { &manager_type::manage }, &invoker_type::invoke };
936 if (stored_vtable.assign_to(f, functor)) {
937 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
938 if (boost::has_trivial_copy_constructor<Functor>::value &&
939 boost::has_trivial_destructor<Functor>::value &&
940 detail::function::function_allows_small_object_optimization<Functor>::value)
941 value |= static_cast<size_t>(0x01);
942 vtable = reinterpret_cast<detail::function::vtable_base *>(value);
947 template<typename Functor,typename Allocator>
948 void assign_to_a(Functor f,Allocator a)
950 using detail::function::vtable_base;
952 typedef typename detail::function::get_function_tag<Functor>::type tag;
953 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
954 typedef typename get_invoker::
955 template apply_a<Functor, R BOOST_FUNCTION_COMMA
956 BOOST_FUNCTION_TEMPLATE_ARGS,
960 typedef typename handler_type::invoker_type invoker_type;
961 typedef typename handler_type::manager_type manager_type;
963 // Note: it is extremely important that this initialization use
964 // static initialization. Otherwise, we will have a race
965 // condition here in multi-threaded code. See
966 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
967 static const vtable_type stored_vtable =
968 { { &manager_type::manage }, &invoker_type::invoke };
970 if (stored_vtable.assign_to_a(f, functor, a)) {
971 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
972 if (boost::has_trivial_copy_constructor<Functor>::value &&
973 boost::has_trivial_destructor<Functor>::value &&
974 detail::function::function_allows_small_object_optimization<Functor>::value)
975 value |= static_cast<std::size_t>(0x01);
976 vtable = reinterpret_cast<detail::function::vtable_base *>(value);
981 // Moves the value from the specified argument to *this. If the argument
982 // has its function object allocated on the heap, move_assign will pass
983 // its buffer to *this, and set the argument's buffer pointer to NULL.
984 void move_assign(BOOST_FUNCTION_FUNCTION& f)
991 this->vtable = f.vtable;
992 if (this->has_trivial_copy_and_destroy())
993 this->functor = f.functor;
995 get_vtable()->base.manager(f.functor, this->functor,
996 boost::detail::function::move_functor_tag);
1001 } BOOST_CATCH (...) {
1009 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1010 inline void swap(BOOST_FUNCTION_FUNCTION<
1011 R BOOST_FUNCTION_COMMA
1012 BOOST_FUNCTION_TEMPLATE_ARGS
1014 BOOST_FUNCTION_FUNCTION<
1015 R BOOST_FUNCTION_COMMA
1016 BOOST_FUNCTION_TEMPLATE_ARGS
1022 // Poison comparisons between boost::function objects of the same type.
1023 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1024 void operator==(const BOOST_FUNCTION_FUNCTION<
1025 R BOOST_FUNCTION_COMMA
1026 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1027 const BOOST_FUNCTION_FUNCTION<
1028 R BOOST_FUNCTION_COMMA
1029 BOOST_FUNCTION_TEMPLATE_ARGS>&);
1030 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1031 void operator!=(const BOOST_FUNCTION_FUNCTION<
1032 R BOOST_FUNCTION_COMMA
1033 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1034 const BOOST_FUNCTION_FUNCTION<
1035 R BOOST_FUNCTION_COMMA
1036 BOOST_FUNCTION_TEMPLATE_ARGS>& );
1038 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1040 #if BOOST_FUNCTION_NUM_ARGS == 0
1041 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
1043 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
1046 template<typename R BOOST_FUNCTION_COMMA
1047 BOOST_FUNCTION_TEMPLATE_PARMS>
1048 class function<BOOST_FUNCTION_PARTIAL_SPEC>
1049 : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1051 typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
1052 typedef function self_type;
1054 struct clear_type {};
1058 function() : base_type() {}
1060 template<typename Functor>
1062 #ifndef BOOST_NO_SFINAE
1063 ,typename enable_if_c<
1064 (boost::type_traits::ice_not<
1065 (is_integral<Functor>::value)>::value),
1072 template<typename Functor,typename Allocator>
1073 function(Functor f, Allocator a
1074 #ifndef BOOST_NO_SFINAE
1075 ,typename enable_if_c<
1076 (boost::type_traits::ice_not<
1077 (is_integral<Functor>::value)>::value),
1085 #ifndef BOOST_NO_SFINAE
1086 function(clear_type*) : base_type() {}
1089 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1091 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1093 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1094 // Move constructors
1095 function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
1096 function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
1099 self_type& operator=(const self_type& f)
1101 self_type(f).swap(*this);
1105 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1106 self_type& operator=(self_type&& f)
1108 self_type(static_cast<self_type&&>(f)).swap(*this);
1113 template<typename Functor>
1114 #ifndef BOOST_NO_SFINAE
1115 typename enable_if_c<
1116 (boost::type_traits::ice_not<
1117 (is_integral<Functor>::value)>::value),
1122 operator=(Functor f)
1124 self_type(f).swap(*this);
1128 #ifndef BOOST_NO_SFINAE
1129 self_type& operator=(clear_type*)
1136 self_type& operator=(const base_type& f)
1138 self_type(f).swap(*this);
1142 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1143 self_type& operator=(base_type&& f)
1145 self_type(static_cast<base_type&&>(f)).swap(*this);
1151 #undef BOOST_FUNCTION_PARTIAL_SPEC
1152 #endif // have partial specialization
1154 } // end namespace boost
1156 // Cleanup after ourselves...
1157 #undef BOOST_FUNCTION_VTABLE
1158 #undef BOOST_FUNCTION_COMMA
1159 #undef BOOST_FUNCTION_FUNCTION
1160 #undef BOOST_FUNCTION_FUNCTION_INVOKER
1161 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
1162 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
1163 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
1164 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
1165 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
1166 #undef BOOST_FUNCTION_MEMBER_INVOKER
1167 #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
1168 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
1169 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
1170 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
1171 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
1172 #undef BOOST_FUNCTION_GET_INVOKER
1173 #undef BOOST_FUNCTION_TEMPLATE_PARMS
1174 #undef BOOST_FUNCTION_TEMPLATE_ARGS
1175 #undef BOOST_FUNCTION_PARMS
1176 #undef BOOST_FUNCTION_PARM
1177 #undef BOOST_FUNCTION_ARGS
1178 #undef BOOST_FUNCTION_ARG_TYPE
1179 #undef BOOST_FUNCTION_ARG_TYPES
1180 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
1181 #undef BOOST_FUNCTION_RETURN
1183 #if defined(BOOST_MSVC)
1184 # pragma warning( pop )