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)
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)
497 typedef typename get_function_tag<F>::type tag;
498 return assign_to_a(f, functor, a, tag());
501 void clear(function_buffer& functor)
504 base.manager(functor, functor, destroy_functor_tag);
509 template<typename FunctionPtr>
511 assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
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 = (void (*)())(f);
523 template<typename FunctionPtr,typename Allocator>
525 assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag)
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)
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(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)
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(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_)
566 new ((void*)&functor.data) FunctionObj(f);
568 template<typename FunctionObj,typename Allocator>
570 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_)
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_)
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_)
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)
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)
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)
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)
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) & ~(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 ~BOOST_FUNCTION_FUNCTION() { clear(); }
754 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
755 // MSVC 6.0 and prior require all definitions to be inline, but
756 // these definitions can become very costly.
757 result_type operator()(BOOST_FUNCTION_PARMS) const
760 boost::throw_exception(bad_function_call());
762 return get_vtable()->invoker
763 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
766 result_type operator()(BOOST_FUNCTION_PARMS) const;
769 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
770 // when to use self_type is obnoxious. MSVC cannot handle self_type as
771 // the return type of these assignment operators, but Borland C++ cannot
772 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
774 template<typename Functor>
775 #ifndef BOOST_NO_SFINAE
776 typename enable_if_c<
777 (boost::type_traits::ice_not<
778 (is_integral<Functor>::value)>::value),
779 BOOST_FUNCTION_FUNCTION&>::type
781 BOOST_FUNCTION_FUNCTION&
783 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
788 } BOOST_CATCH (...) {
795 template<typename Functor,typename Allocator>
796 void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
800 this->assign_to_a(f,a);
801 } BOOST_CATCH (...) {
808 #ifndef BOOST_NO_SFINAE
809 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
815 BOOST_FUNCTION_FUNCTION& operator=(int zero)
817 BOOST_ASSERT(zero == 0);
823 // Assignment from another BOOST_FUNCTION_FUNCTION
824 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
831 this->assign_to_own(f);
832 } BOOST_CATCH (...) {
840 void swap(BOOST_FUNCTION_FUNCTION& other)
845 BOOST_FUNCTION_FUNCTION tmp;
846 tmp.move_assign(*this);
847 this->move_assign(other);
848 other.move_assign(tmp);
851 // Clear out a target, if there is one
855 if (!this->has_trivial_copy_and_destroy())
856 get_vtable()->clear(this->functor);
861 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
862 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
863 operator bool () const { return !this->empty(); }
870 typedef void (dummy::*safe_bool)();
873 operator safe_bool () const
874 { return (this->empty())? 0 : &dummy::nonnull; }
876 bool operator!() const
877 { return this->empty(); }
881 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
884 this->vtable = f.vtable;
885 if (this->has_trivial_copy_and_destroy())
886 this->functor = f.functor;
888 get_vtable()->base.manager(f.functor, this->functor,
889 boost::detail::function::clone_functor_tag);
893 template<typename Functor>
894 void assign_to(Functor f)
896 using detail::function::vtable_base;
898 typedef typename detail::function::get_function_tag<Functor>::type tag;
899 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
900 typedef typename get_invoker::
901 template apply<Functor, R BOOST_FUNCTION_COMMA
902 BOOST_FUNCTION_TEMPLATE_ARGS>
905 typedef typename handler_type::invoker_type invoker_type;
906 typedef typename handler_type::manager_type manager_type;
908 // Note: it is extremely important that this initialization use
909 // static initialization. Otherwise, we will have a race
910 // condition here in multi-threaded code. See
911 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
912 static vtable_type stored_vtable =
913 { { &manager_type::manage }, &invoker_type::invoke };
915 if (stored_vtable.assign_to(f, functor)) {
916 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
917 if (boost::has_trivial_copy_constructor<Functor>::value &&
918 boost::has_trivial_destructor<Functor>::value &&
919 detail::function::function_allows_small_object_optimization<Functor>::value)
920 value |= (std::size_t)0x01;
921 vtable = reinterpret_cast<detail::function::vtable_base *>(value);
926 template<typename Functor,typename Allocator>
927 void assign_to_a(Functor f,Allocator a)
929 using detail::function::vtable_base;
931 typedef typename detail::function::get_function_tag<Functor>::type tag;
932 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
933 typedef typename get_invoker::
934 template apply_a<Functor, R BOOST_FUNCTION_COMMA
935 BOOST_FUNCTION_TEMPLATE_ARGS,
939 typedef typename handler_type::invoker_type invoker_type;
940 typedef typename handler_type::manager_type manager_type;
942 // Note: it is extremely important that this initialization use
943 // static initialization. Otherwise, we will have a race
944 // condition here in multi-threaded code. See
945 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
946 static vtable_type stored_vtable =
947 { { &manager_type::manage }, &invoker_type::invoke };
949 if (stored_vtable.assign_to_a(f, functor, a)) {
950 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
951 if (boost::has_trivial_copy_constructor<Functor>::value &&
952 boost::has_trivial_destructor<Functor>::value &&
953 detail::function::function_allows_small_object_optimization<Functor>::value)
954 value |= (std::size_t)0x01;
955 vtable = reinterpret_cast<detail::function::vtable_base *>(value);
960 // Moves the value from the specified argument to *this. If the argument
961 // has its function object allocated on the heap, move_assign will pass
962 // its buffer to *this, and set the argument's buffer pointer to NULL.
963 void move_assign(BOOST_FUNCTION_FUNCTION& f)
970 this->vtable = f.vtable;
971 if (this->has_trivial_copy_and_destroy())
972 this->functor = f.functor;
974 get_vtable()->base.manager(f.functor, this->functor,
975 boost::detail::function::move_functor_tag);
980 } BOOST_CATCH (...) {
988 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
989 inline void swap(BOOST_FUNCTION_FUNCTION<
990 R BOOST_FUNCTION_COMMA
991 BOOST_FUNCTION_TEMPLATE_ARGS
993 BOOST_FUNCTION_FUNCTION<
994 R BOOST_FUNCTION_COMMA
995 BOOST_FUNCTION_TEMPLATE_ARGS
1001 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
1002 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1003 typename BOOST_FUNCTION_FUNCTION<
1004 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type
1006 BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1007 ::operator()(BOOST_FUNCTION_PARMS) const
1010 boost::throw_exception(bad_function_call());
1012 return get_vtable()->invoker
1013 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
1017 // Poison comparisons between boost::function objects of the same type.
1018 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1019 void operator==(const BOOST_FUNCTION_FUNCTION<
1020 R BOOST_FUNCTION_COMMA
1021 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1022 const BOOST_FUNCTION_FUNCTION<
1023 R BOOST_FUNCTION_COMMA
1024 BOOST_FUNCTION_TEMPLATE_ARGS>&);
1025 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1026 void operator!=(const BOOST_FUNCTION_FUNCTION<
1027 R BOOST_FUNCTION_COMMA
1028 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1029 const BOOST_FUNCTION_FUNCTION<
1030 R BOOST_FUNCTION_COMMA
1031 BOOST_FUNCTION_TEMPLATE_ARGS>& );
1033 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1035 #if BOOST_FUNCTION_NUM_ARGS == 0
1036 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
1038 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
1041 template<typename R BOOST_FUNCTION_COMMA
1042 BOOST_FUNCTION_TEMPLATE_PARMS>
1043 class function<BOOST_FUNCTION_PARTIAL_SPEC>
1044 : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1046 typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
1047 typedef function self_type;
1049 struct clear_type {};
1053 function() : base_type() {}
1055 template<typename Functor>
1057 #ifndef BOOST_NO_SFINAE
1058 ,typename enable_if_c<
1059 (boost::type_traits::ice_not<
1060 (is_integral<Functor>::value)>::value),
1067 template<typename Functor,typename Allocator>
1068 function(Functor f, Allocator a
1069 #ifndef BOOST_NO_SFINAE
1070 ,typename enable_if_c<
1071 (boost::type_traits::ice_not<
1072 (is_integral<Functor>::value)>::value),
1080 #ifndef BOOST_NO_SFINAE
1081 function(clear_type*) : base_type() {}
1084 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1086 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1088 self_type& operator=(const self_type& f)
1090 self_type(f).swap(*this);
1094 template<typename Functor>
1095 #ifndef BOOST_NO_SFINAE
1096 typename enable_if_c<
1097 (boost::type_traits::ice_not<
1098 (is_integral<Functor>::value)>::value),
1103 operator=(Functor f)
1105 self_type(f).swap(*this);
1109 #ifndef BOOST_NO_SFINAE
1110 self_type& operator=(clear_type*)
1117 self_type& operator=(const base_type& f)
1119 self_type(f).swap(*this);
1124 #undef BOOST_FUNCTION_PARTIAL_SPEC
1125 #endif // have partial specialization
1127 } // end namespace boost
1129 // Cleanup after ourselves...
1130 #undef BOOST_FUNCTION_VTABLE
1131 #undef BOOST_FUNCTION_COMMA
1132 #undef BOOST_FUNCTION_FUNCTION
1133 #undef BOOST_FUNCTION_FUNCTION_INVOKER
1134 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
1135 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
1136 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
1137 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
1138 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
1139 #undef BOOST_FUNCTION_MEMBER_INVOKER
1140 #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
1141 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
1142 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
1143 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
1144 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
1145 #undef BOOST_FUNCTION_GET_INVOKER
1146 #undef BOOST_FUNCTION_TEMPLATE_PARMS
1147 #undef BOOST_FUNCTION_TEMPLATE_ARGS
1148 #undef BOOST_FUNCTION_PARMS
1149 #undef BOOST_FUNCTION_PARM
1150 #undef BOOST_FUNCTION_ARGS
1151 #undef BOOST_FUNCTION_ARG_TYPE
1152 #undef BOOST_FUNCTION_ARG_TYPES
1153 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
1154 #undef BOOST_FUNCTION_RETURN
1156 #if defined(BOOST_MSVC)
1157 # pragma warning( pop )