1 // Boost.Function library
\r
3 // Copyright Douglas Gregor 2001-2006
\r
4 // Copyright Emil Dotchevski 2007
\r
5 // Use, modification and distribution is subject to the Boost Software License, Version 1.0.
\r
6 // (See accompanying file LICENSE_1_0.txt or copy at
\r
7 // http://www.boost.org/LICENSE_1_0.txt)
\r
9 // For more information, see http://www.boost.org
\r
11 // Note: this header is a header template and must NOT have multiple-inclusion
\r
13 #include <boost/function/detail/prologue.hpp>
\r
14 #include <boost/detail/no_exceptions_support.hpp>
\r
16 #if defined(BOOST_MSVC)
\r
17 # pragma warning( push )
\r
18 # pragma warning( disable : 4127 ) // "conditional expression is constant"
\r
21 #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
\r
23 #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
\r
25 #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
\r
27 #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
\r
29 #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
\r
31 #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
\r
32 typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
\r
34 #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
\r
36 // Comma if nonzero number of arguments
\r
37 #if BOOST_FUNCTION_NUM_ARGS == 0
\r
38 # define BOOST_FUNCTION_COMMA
\r
40 # define BOOST_FUNCTION_COMMA ,
\r
41 #endif // BOOST_FUNCTION_NUM_ARGS > 0
\r
43 // Class names used in this version of the code
\r
44 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
\r
45 #define BOOST_FUNCTION_FUNCTION_INVOKER \
\r
46 BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
47 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
\r
48 BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
49 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
\r
50 BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
51 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
\r
52 BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
53 #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
\r
54 BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
55 #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
\r
56 BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
57 #define BOOST_FUNCTION_MEMBER_INVOKER \
\r
58 BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
59 #define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
\r
60 BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
61 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
\r
62 BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
63 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
\r
64 BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
65 #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
\r
66 BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
67 #define BOOST_FUNCTION_GET_MEMBER_INVOKER \
\r
68 BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
69 #define BOOST_FUNCTION_GET_INVOKER \
\r
70 BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
\r
71 #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
\r
73 #ifndef BOOST_NO_VOID_RETURNS
\r
74 # define BOOST_FUNCTION_VOID_RETURN_TYPE void
\r
75 # define BOOST_FUNCTION_RETURN(X) X
\r
77 # define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable
\r
78 # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
\r
83 namespace function {
\r
85 typename FunctionPtr,
\r
86 typename R BOOST_FUNCTION_COMMA
\r
87 BOOST_FUNCTION_TEMPLATE_PARMS
\r
89 struct BOOST_FUNCTION_FUNCTION_INVOKER
\r
91 static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
\r
92 BOOST_FUNCTION_PARMS)
\r
94 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
\r
95 return f(BOOST_FUNCTION_ARGS);
\r
100 typename FunctionPtr,
\r
101 typename R BOOST_FUNCTION_COMMA
\r
102 BOOST_FUNCTION_TEMPLATE_PARMS
\r
104 struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
\r
106 static BOOST_FUNCTION_VOID_RETURN_TYPE
\r
107 invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
\r
108 BOOST_FUNCTION_PARMS)
\r
111 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
\r
112 BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
\r
117 typename FunctionObj,
\r
118 typename R BOOST_FUNCTION_COMMA
\r
119 BOOST_FUNCTION_TEMPLATE_PARMS
\r
121 struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
\r
123 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
\r
124 BOOST_FUNCTION_PARMS)
\r
128 if (function_allows_small_object_optimization<FunctionObj>::value)
\r
129 f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
\r
131 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
\r
132 return (*f)(BOOST_FUNCTION_ARGS);
\r
137 typename FunctionObj,
\r
138 typename R BOOST_FUNCTION_COMMA
\r
139 BOOST_FUNCTION_TEMPLATE_PARMS
\r
141 struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
\r
143 static BOOST_FUNCTION_VOID_RETURN_TYPE
\r
144 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
\r
145 BOOST_FUNCTION_PARMS)
\r
149 if (function_allows_small_object_optimization<FunctionObj>::value)
\r
150 f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
\r
152 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
\r
153 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
\r
158 typename FunctionObj,
\r
159 typename R BOOST_FUNCTION_COMMA
\r
160 BOOST_FUNCTION_TEMPLATE_PARMS
\r
162 struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
\r
164 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
\r
165 BOOST_FUNCTION_PARMS)
\r
169 reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
\r
170 return (*f)(BOOST_FUNCTION_ARGS);
\r
175 typename FunctionObj,
\r
176 typename R BOOST_FUNCTION_COMMA
\r
177 BOOST_FUNCTION_TEMPLATE_PARMS
\r
179 struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
\r
181 static BOOST_FUNCTION_VOID_RETURN_TYPE
\r
182 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
\r
183 BOOST_FUNCTION_PARMS)
\r
187 reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
\r
188 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
\r
192 #if BOOST_FUNCTION_NUM_ARGS > 0
\r
193 /* Handle invocation of member pointers. */
\r
195 typename MemberPtr,
\r
196 typename R BOOST_FUNCTION_COMMA
\r
197 BOOST_FUNCTION_TEMPLATE_PARMS
\r
199 struct BOOST_FUNCTION_MEMBER_INVOKER
\r
201 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
\r
202 BOOST_FUNCTION_PARMS)
\r
206 reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
\r
207 return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
\r
212 typename MemberPtr,
\r
213 typename R BOOST_FUNCTION_COMMA
\r
214 BOOST_FUNCTION_TEMPLATE_PARMS
\r
216 struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
\r
218 static BOOST_FUNCTION_VOID_RETURN_TYPE
\r
219 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
\r
220 BOOST_FUNCTION_PARMS)
\r
224 reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
\r
225 BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
\r
231 typename FunctionPtr,
\r
232 typename R BOOST_FUNCTION_COMMA
\r
233 BOOST_FUNCTION_TEMPLATE_PARMS
\r
235 struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
\r
237 typedef typename mpl::if_c<(is_void<R>::value),
\r
238 BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
\r
240 R BOOST_FUNCTION_COMMA
\r
241 BOOST_FUNCTION_TEMPLATE_ARGS
\r
243 BOOST_FUNCTION_FUNCTION_INVOKER<
\r
245 R BOOST_FUNCTION_COMMA
\r
246 BOOST_FUNCTION_TEMPLATE_ARGS
\r
252 typename FunctionObj,
\r
253 typename R BOOST_FUNCTION_COMMA
\r
254 BOOST_FUNCTION_TEMPLATE_PARMS
\r
256 struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
\r
258 typedef typename mpl::if_c<(is_void<R>::value),
\r
259 BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
\r
261 R BOOST_FUNCTION_COMMA
\r
262 BOOST_FUNCTION_TEMPLATE_ARGS
\r
264 BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
\r
266 R BOOST_FUNCTION_COMMA
\r
267 BOOST_FUNCTION_TEMPLATE_ARGS
\r
273 typename FunctionObj,
\r
274 typename R BOOST_FUNCTION_COMMA
\r
275 BOOST_FUNCTION_TEMPLATE_PARMS
\r
277 struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
\r
279 typedef typename mpl::if_c<(is_void<R>::value),
\r
280 BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
\r
282 R BOOST_FUNCTION_COMMA
\r
283 BOOST_FUNCTION_TEMPLATE_ARGS
\r
285 BOOST_FUNCTION_FUNCTION_REF_INVOKER<
\r
287 R BOOST_FUNCTION_COMMA
\r
288 BOOST_FUNCTION_TEMPLATE_ARGS
\r
293 #if BOOST_FUNCTION_NUM_ARGS > 0
\r
294 /* Retrieve the appropriate invoker for a member pointer. */
\r
296 typename MemberPtr,
\r
297 typename R BOOST_FUNCTION_COMMA
\r
298 BOOST_FUNCTION_TEMPLATE_PARMS
\r
300 struct BOOST_FUNCTION_GET_MEMBER_INVOKER
\r
302 typedef typename mpl::if_c<(is_void<R>::value),
\r
303 BOOST_FUNCTION_VOID_MEMBER_INVOKER<
\r
305 R BOOST_FUNCTION_COMMA
\r
306 BOOST_FUNCTION_TEMPLATE_ARGS
\r
308 BOOST_FUNCTION_MEMBER_INVOKER<
\r
310 R BOOST_FUNCTION_COMMA
\r
311 BOOST_FUNCTION_TEMPLATE_ARGS
\r
317 /* Given the tag returned by get_function_tag, retrieve the
\r
318 actual invoker that will be used for the given function
\r
321 Each specialization contains an "apply" nested class template
\r
322 that accepts the function object, return type, function
\r
323 argument types, and allocator. The resulting "apply" class
\r
324 contains two typedefs, "invoker_type" and "manager_type",
\r
325 which correspond to the invoker and manager types. */
\r
326 template<typename Tag>
\r
327 struct BOOST_FUNCTION_GET_INVOKER { };
\r
329 /* Retrieve the invoker for a function pointer. */
\r
331 struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
\r
333 template<typename FunctionPtr,
\r
334 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
\r
337 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
\r
339 R BOOST_FUNCTION_COMMA
\r
340 BOOST_FUNCTION_TEMPLATE_ARGS
\r
344 typedef functor_manager<FunctionPtr> manager_type;
\r
347 template<typename FunctionPtr,
\r
348 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
\r
349 typename Allocator>
\r
352 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
\r
354 R BOOST_FUNCTION_COMMA
\r
355 BOOST_FUNCTION_TEMPLATE_ARGS
\r
359 typedef functor_manager<FunctionPtr> manager_type;
\r
363 #if BOOST_FUNCTION_NUM_ARGS > 0
\r
364 /* Retrieve the invoker for a member pointer. */
\r
366 struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
\r
368 template<typename MemberPtr,
\r
369 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
\r
372 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
\r
374 R BOOST_FUNCTION_COMMA
\r
375 BOOST_FUNCTION_TEMPLATE_ARGS
\r
379 typedef functor_manager<MemberPtr> manager_type;
\r
382 template<typename MemberPtr,
\r
383 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
\r
384 typename Allocator>
\r
387 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
\r
389 R BOOST_FUNCTION_COMMA
\r
390 BOOST_FUNCTION_TEMPLATE_ARGS
\r
394 typedef functor_manager<MemberPtr> manager_type;
\r
399 /* Retrieve the invoker for a function object. */
\r
401 struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
\r
403 template<typename FunctionObj,
\r
404 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
\r
407 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
\r
409 R BOOST_FUNCTION_COMMA
\r
410 BOOST_FUNCTION_TEMPLATE_ARGS
\r
414 typedef functor_manager<FunctionObj> manager_type;
\r
417 template<typename FunctionObj,
\r
418 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
\r
419 typename Allocator>
\r
422 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
\r
424 R BOOST_FUNCTION_COMMA
\r
425 BOOST_FUNCTION_TEMPLATE_ARGS
\r
429 typedef functor_manager_a<FunctionObj, Allocator> manager_type;
\r
433 /* Retrieve the invoker for a reference to a function object. */
\r
435 struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
\r
437 template<typename RefWrapper,
\r
438 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
\r
441 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
\r
442 typename RefWrapper::type,
\r
443 R BOOST_FUNCTION_COMMA
\r
444 BOOST_FUNCTION_TEMPLATE_ARGS
\r
448 typedef reference_manager<typename RefWrapper::type> manager_type;
\r
451 template<typename RefWrapper,
\r
452 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
\r
453 typename Allocator>
\r
456 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
\r
457 typename RefWrapper::type,
\r
458 R BOOST_FUNCTION_COMMA
\r
459 BOOST_FUNCTION_TEMPLATE_ARGS
\r
463 typedef reference_manager<typename RefWrapper::type> manager_type;
\r
469 * vtable for a specific boost::function instance. This
\r
470 * structure must be an aggregate so that we can use static
\r
471 * initialization in boost::function's assign_to and assign_to_a
\r
472 * members. It therefore cannot have any constructors,
\r
473 * destructors, base classes, etc.
\r
475 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
\r
476 struct BOOST_FUNCTION_VTABLE
\r
478 #ifndef BOOST_NO_VOID_RETURNS
\r
479 typedef R result_type;
\r
481 typedef typename function_return_type<R>::type result_type;
\r
482 #endif // BOOST_NO_VOID_RETURNS
\r
484 typedef result_type (*invoker_type)(function_buffer&
\r
485 BOOST_FUNCTION_COMMA
\r
486 BOOST_FUNCTION_TEMPLATE_ARGS);
\r
488 template<typename F>
\r
489 bool assign_to(F f, function_buffer& functor)
\r
491 typedef typename get_function_tag<F>::type tag;
\r
492 return assign_to(f, functor, tag());
\r
494 template<typename F,typename Allocator>
\r
495 bool assign_to_a(F f, function_buffer& functor, Allocator a)
\r
497 typedef typename get_function_tag<F>::type tag;
\r
498 return assign_to_a(f, functor, a, tag());
\r
501 void clear(function_buffer& functor)
\r
504 base.manager(functor, functor, destroy_functor_tag);
\r
508 // Function pointers
\r
509 template<typename FunctionPtr>
\r
511 assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
\r
513 this->clear(functor);
\r
515 // should be a reinterpret cast, but some compilers insist
\r
516 // on giving cv-qualifiers to free functions
\r
517 functor.func_ptr = (void (*)())(f);
\r
523 template<typename FunctionPtr,typename Allocator>
\r
525 assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag)
\r
527 return assign_to(f,functor,function_ptr_tag());
\r
531 #if BOOST_FUNCTION_NUM_ARGS > 0
\r
532 template<typename MemberPtr>
\r
533 bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag)
\r
535 // DPG TBD: Add explicit support for member function
\r
536 // objects, so we invoke through mem_fn() but we retain the
\r
537 // right target_type() values.
\r
539 this->assign_to(mem_fn(f), functor);
\r
545 template<typename MemberPtr,typename Allocator>
\r
546 bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag)
\r
548 // DPG TBD: Add explicit support for member function
\r
549 // objects, so we invoke through mem_fn() but we retain the
\r
550 // right target_type() values.
\r
552 this->assign_to_a(mem_fn(f), functor, a);
\r
558 #endif // BOOST_FUNCTION_NUM_ARGS > 0
\r
560 // Function objects
\r
561 // Assign to a function object using the small object optimization
\r
562 template<typename FunctionObj>
\r
564 assign_functor(FunctionObj f, function_buffer& functor, mpl::true_)
\r
566 new ((void*)&functor.data) FunctionObj(f);
\r
568 template<typename FunctionObj,typename Allocator>
\r
570 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_)
\r
572 assign_functor(f,functor,mpl::true_());
\r
575 // Assign to a function object allocated on the heap.
\r
576 template<typename FunctionObj>
\r
578 assign_functor(FunctionObj f, function_buffer& functor, mpl::false_)
\r
580 functor.obj_ptr = new FunctionObj(f);
\r
582 template<typename FunctionObj,typename Allocator>
\r
584 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_)
\r
586 typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
\r
587 typedef typename Allocator::template rebind<functor_wrapper_type>::other
\r
588 wrapper_allocator_type;
\r
589 typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
\r
590 wrapper_allocator_type wrapper_allocator(a);
\r
591 wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
\r
592 wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
\r
593 functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
\r
594 functor.obj_ptr = new_f;
\r
597 template<typename FunctionObj>
\r
599 assign_to(FunctionObj f, function_buffer& functor, function_obj_tag)
\r
601 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
\r
602 assign_functor(f, functor,
\r
603 mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
\r
609 template<typename FunctionObj,typename Allocator>
\r
611 assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag)
\r
613 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
\r
614 assign_functor_a(f, functor, a,
\r
615 mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
\r
622 // Reference to a function object
\r
623 template<typename FunctionObj>
\r
625 assign_to(const reference_wrapper<FunctionObj>& f,
\r
626 function_buffer& functor, function_obj_ref_tag)
\r
628 functor.obj_ref.obj_ptr = (void *)f.get_pointer();
\r
629 functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
\r
630 functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
\r
633 template<typename FunctionObj,typename Allocator>
\r
635 assign_to_a(const reference_wrapper<FunctionObj>& f,
\r
636 function_buffer& functor, Allocator, function_obj_ref_tag)
\r
638 return assign_to(f,functor,function_obj_ref_tag());
\r
643 invoker_type invoker;
\r
645 } // end namespace function
\r
646 } // end namespace detail
\r
649 typename R BOOST_FUNCTION_COMMA
\r
650 BOOST_FUNCTION_TEMPLATE_PARMS
\r
652 class BOOST_FUNCTION_FUNCTION : public function_base
\r
654 #if BOOST_FUNCTION_NUM_ARGS == 1
\r
656 , public std::unary_function<T0,R>
\r
658 #elif BOOST_FUNCTION_NUM_ARGS == 2
\r
660 , public std::binary_function<T0,T1,R>
\r
666 #ifndef BOOST_NO_VOID_RETURNS
\r
667 typedef R result_type;
\r
669 typedef typename boost::detail::function::function_return_type<R>::type
\r
671 #endif // BOOST_NO_VOID_RETURNS
\r
674 typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
\r
675 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
\r
678 vtable_type* get_vtable() const {
\r
679 return reinterpret_cast<vtable_type*>(
\r
680 reinterpret_cast<std::size_t>(vtable) & ~(std::size_t)0x01);
\r
683 struct clear_type {};
\r
686 BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
\r
688 // add signature for boost::lambda
\r
689 template<typename Args>
\r
692 typedef result_type type;
\r
695 #if BOOST_FUNCTION_NUM_ARGS == 1
\r
696 typedef T0 argument_type;
\r
697 #elif BOOST_FUNCTION_NUM_ARGS == 2
\r
698 typedef T0 first_argument_type;
\r
699 typedef T1 second_argument_type;
\r
702 BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
\r
703 BOOST_FUNCTION_ARG_TYPES
\r
705 typedef BOOST_FUNCTION_FUNCTION self_type;
\r
707 BOOST_FUNCTION_FUNCTION() : function_base() { }
\r
709 // MSVC chokes if the following two constructors are collapsed into
\r
710 // one with a default parameter.
\r
711 template<typename Functor>
\r
712 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
\r
713 #ifndef BOOST_NO_SFINAE
\r
714 ,typename enable_if_c<
\r
715 (boost::type_traits::ice_not<
\r
716 (is_integral<Functor>::value)>::value),
\r
718 #endif // BOOST_NO_SFINAE
\r
722 this->assign_to(f);
\r
724 template<typename Functor,typename Allocator>
\r
725 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
\r
726 #ifndef BOOST_NO_SFINAE
\r
727 ,typename enable_if_c<
\r
728 (boost::type_traits::ice_not<
\r
729 (is_integral<Functor>::value)>::value),
\r
731 #endif // BOOST_NO_SFINAE
\r
735 this->assign_to_a(f,a);
\r
738 #ifndef BOOST_NO_SFINAE
\r
739 BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
\r
741 BOOST_FUNCTION_FUNCTION(int zero) : function_base()
\r
743 BOOST_ASSERT(zero == 0);
\r
747 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
\r
749 this->assign_to_own(f);
\r
752 ~BOOST_FUNCTION_FUNCTION() { clear(); }
\r
754 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
\r
755 // MSVC 6.0 and prior require all definitions to be inline, but
\r
756 // these definitions can become very costly.
\r
757 result_type operator()(BOOST_FUNCTION_PARMS) const
\r
760 boost::throw_exception(bad_function_call());
\r
762 return get_vtable()->invoker
\r
763 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
\r
766 result_type operator()(BOOST_FUNCTION_PARMS) const;
\r
769 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
\r
770 // when to use self_type is obnoxious. MSVC cannot handle self_type as
\r
771 // the return type of these assignment operators, but Borland C++ cannot
\r
772 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
\r
774 template<typename Functor>
\r
775 #ifndef BOOST_NO_SFINAE
\r
776 typename enable_if_c<
\r
777 (boost::type_traits::ice_not<
\r
778 (is_integral<Functor>::value)>::value),
\r
779 BOOST_FUNCTION_FUNCTION&>::type
\r
781 BOOST_FUNCTION_FUNCTION&
\r
783 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
\r
787 this->assign_to(f);
\r
788 } BOOST_CATCH (...) {
\r
795 template<typename Functor,typename Allocator>
\r
796 void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
\r
800 this->assign_to_a(f,a);
\r
801 } BOOST_CATCH (...) {
\r
808 #ifndef BOOST_NO_SFINAE
\r
809 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
\r
815 BOOST_FUNCTION_FUNCTION& operator=(int zero)
\r
817 BOOST_ASSERT(zero == 0);
\r
823 // Assignment from another BOOST_FUNCTION_FUNCTION
\r
824 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
\r
831 this->assign_to_own(f);
\r
832 } BOOST_CATCH (...) {
\r
840 void swap(BOOST_FUNCTION_FUNCTION& other)
\r
842 if (&other == this)
\r
845 BOOST_FUNCTION_FUNCTION tmp;
\r
846 tmp.move_assign(*this);
\r
847 this->move_assign(other);
\r
848 other.move_assign(tmp);
\r
851 // Clear out a target, if there is one
\r
855 if (!this->has_trivial_copy_and_destroy())
\r
856 get_vtable()->clear(this->functor);
\r
861 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
\r
862 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
\r
863 operator bool () const { return !this->empty(); }
\r
870 typedef void (dummy::*safe_bool)();
\r
873 operator safe_bool () const
\r
874 { return (this->empty())? 0 : &dummy::nonnull; }
\r
876 bool operator!() const
\r
877 { return this->empty(); }
\r
881 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
\r
884 this->vtable = f.vtable;
\r
885 if (this->has_trivial_copy_and_destroy())
\r
886 this->functor = f.functor;
\r
888 get_vtable()->base.manager(f.functor, this->functor,
\r
889 boost::detail::function::clone_functor_tag);
\r
893 template<typename Functor>
\r
894 void assign_to(Functor f)
\r
896 using detail::function::vtable_base;
\r
898 typedef typename detail::function::get_function_tag<Functor>::type tag;
\r
899 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
\r
900 typedef typename get_invoker::
\r
901 template apply<Functor, R BOOST_FUNCTION_COMMA
\r
902 BOOST_FUNCTION_TEMPLATE_ARGS>
\r
905 typedef typename handler_type::invoker_type invoker_type;
\r
906 typedef typename handler_type::manager_type manager_type;
\r
908 // Note: it is extremely important that this initialization use
\r
909 // static initialization. Otherwise, we will have a race
\r
910 // condition here in multi-threaded code. See
\r
911 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
\r
912 static vtable_type stored_vtable =
\r
913 { { &manager_type::manage }, &invoker_type::invoke };
\r
915 if (stored_vtable.assign_to(f, functor)) {
\r
916 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
\r
917 if (boost::has_trivial_copy_constructor<Functor>::value &&
\r
918 boost::has_trivial_destructor<Functor>::value &&
\r
919 detail::function::function_allows_small_object_optimization<Functor>::value)
\r
920 value |= (std::size_t)0x01;
\r
921 vtable = reinterpret_cast<detail::function::vtable_base *>(value);
\r
926 template<typename Functor,typename Allocator>
\r
927 void assign_to_a(Functor f,Allocator a)
\r
929 using detail::function::vtable_base;
\r
931 typedef typename detail::function::get_function_tag<Functor>::type tag;
\r
932 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
\r
933 typedef typename get_invoker::
\r
934 template apply_a<Functor, R BOOST_FUNCTION_COMMA
\r
935 BOOST_FUNCTION_TEMPLATE_ARGS,
\r
939 typedef typename handler_type::invoker_type invoker_type;
\r
940 typedef typename handler_type::manager_type manager_type;
\r
942 // Note: it is extremely important that this initialization use
\r
943 // static initialization. Otherwise, we will have a race
\r
944 // condition here in multi-threaded code. See
\r
945 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
\r
946 static vtable_type stored_vtable =
\r
947 { { &manager_type::manage }, &invoker_type::invoke };
\r
949 if (stored_vtable.assign_to_a(f, functor, a)) {
\r
950 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
\r
951 if (boost::has_trivial_copy_constructor<Functor>::value &&
\r
952 boost::has_trivial_destructor<Functor>::value &&
\r
953 detail::function::function_allows_small_object_optimization<Functor>::value)
\r
954 value |= (std::size_t)0x01;
\r
955 vtable = reinterpret_cast<detail::function::vtable_base *>(value);
\r
960 // Moves the value from the specified argument to *this. If the argument
\r
961 // has its function object allocated on the heap, move_assign will pass
\r
962 // its buffer to *this, and set the argument's buffer pointer to NULL.
\r
963 void move_assign(BOOST_FUNCTION_FUNCTION& f)
\r
970 this->vtable = f.vtable;
\r
971 if (this->has_trivial_copy_and_destroy())
\r
972 this->functor = f.functor;
\r
974 get_vtable()->base.manager(f.functor, this->functor,
\r
975 boost::detail::function::move_functor_tag);
\r
980 } BOOST_CATCH (...) {
\r
988 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
\r
989 inline void swap(BOOST_FUNCTION_FUNCTION<
\r
990 R BOOST_FUNCTION_COMMA
\r
991 BOOST_FUNCTION_TEMPLATE_ARGS
\r
993 BOOST_FUNCTION_FUNCTION<
\r
994 R BOOST_FUNCTION_COMMA
\r
995 BOOST_FUNCTION_TEMPLATE_ARGS
\r
1001 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
\r
1002 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
\r
1003 typename BOOST_FUNCTION_FUNCTION<
\r
1004 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type
\r
1006 BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
\r
1007 ::operator()(BOOST_FUNCTION_PARMS) const
\r
1009 if (this->empty())
\r
1010 boost::throw_exception(bad_function_call());
\r
1012 return get_vtable()->invoker
\r
1013 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
\r
1017 // Poison comparisons between boost::function objects of the same type.
\r
1018 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
\r
1019 void operator==(const BOOST_FUNCTION_FUNCTION<
\r
1020 R BOOST_FUNCTION_COMMA
\r
1021 BOOST_FUNCTION_TEMPLATE_ARGS>&,
\r
1022 const BOOST_FUNCTION_FUNCTION<
\r
1023 R BOOST_FUNCTION_COMMA
\r
1024 BOOST_FUNCTION_TEMPLATE_ARGS>&);
\r
1025 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
\r
1026 void operator!=(const BOOST_FUNCTION_FUNCTION<
\r
1027 R BOOST_FUNCTION_COMMA
\r
1028 BOOST_FUNCTION_TEMPLATE_ARGS>&,
\r
1029 const BOOST_FUNCTION_FUNCTION<
\r
1030 R BOOST_FUNCTION_COMMA
\r
1031 BOOST_FUNCTION_TEMPLATE_ARGS>& );
\r
1033 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
\r
1035 #if BOOST_FUNCTION_NUM_ARGS == 0
\r
1036 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
\r
1038 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
\r
1041 template<typename R BOOST_FUNCTION_COMMA
\r
1042 BOOST_FUNCTION_TEMPLATE_PARMS>
\r
1043 class function<BOOST_FUNCTION_PARTIAL_SPEC>
\r
1044 : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
\r
1046 typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
\r
1047 typedef function self_type;
\r
1049 struct clear_type {};
\r
1053 function() : base_type() {}
\r
1055 template<typename Functor>
\r
1056 function(Functor f
\r
1057 #ifndef BOOST_NO_SFINAE
\r
1058 ,typename enable_if_c<
\r
1059 (boost::type_traits::ice_not<
\r
1060 (is_integral<Functor>::value)>::value),
\r
1067 template<typename Functor,typename Allocator>
\r
1068 function(Functor f, Allocator a
\r
1069 #ifndef BOOST_NO_SFINAE
\r
1070 ,typename enable_if_c<
\r
1071 (boost::type_traits::ice_not<
\r
1072 (is_integral<Functor>::value)>::value),
\r
1080 #ifndef BOOST_NO_SFINAE
\r
1081 function(clear_type*) : base_type() {}
\r
1084 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
\r
1086 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
\r
1088 self_type& operator=(const self_type& f)
\r
1090 self_type(f).swap(*this);
\r
1094 template<typename Functor>
\r
1095 #ifndef BOOST_NO_SFINAE
\r
1096 typename enable_if_c<
\r
1097 (boost::type_traits::ice_not<
\r
1098 (is_integral<Functor>::value)>::value),
\r
1103 operator=(Functor f)
\r
1105 self_type(f).swap(*this);
\r
1109 #ifndef BOOST_NO_SFINAE
\r
1110 self_type& operator=(clear_type*)
\r
1117 self_type& operator=(const base_type& f)
\r
1119 self_type(f).swap(*this);
\r
1124 #undef BOOST_FUNCTION_PARTIAL_SPEC
\r
1125 #endif // have partial specialization
\r
1127 } // end namespace boost
\r
1129 // Cleanup after ourselves...
\r
1130 #undef BOOST_FUNCTION_VTABLE
\r
1131 #undef BOOST_FUNCTION_COMMA
\r
1132 #undef BOOST_FUNCTION_FUNCTION
\r
1133 #undef BOOST_FUNCTION_FUNCTION_INVOKER
\r
1134 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
\r
1135 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
\r
1136 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
\r
1137 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
\r
1138 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
\r
1139 #undef BOOST_FUNCTION_MEMBER_INVOKER
\r
1140 #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
\r
1141 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
\r
1142 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
\r
1143 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
\r
1144 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
\r
1145 #undef BOOST_FUNCTION_GET_INVOKER
\r
1146 #undef BOOST_FUNCTION_TEMPLATE_PARMS
\r
1147 #undef BOOST_FUNCTION_TEMPLATE_ARGS
\r
1148 #undef BOOST_FUNCTION_PARMS
\r
1149 #undef BOOST_FUNCTION_PARM
\r
1150 #undef BOOST_FUNCTION_ARGS
\r
1151 #undef BOOST_FUNCTION_ARG_TYPE
\r
1152 #undef BOOST_FUNCTION_ARG_TYPES
\r
1153 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
\r
1154 #undef BOOST_FUNCTION_RETURN
\r
1156 #if defined(BOOST_MSVC)
\r
1157 # pragma warning( pop )
\r