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>
15 #if defined(BOOST_MSVC)
16 # pragma warning( push )
17 # pragma warning( disable : 4127 ) // "conditional expression is constant"
20 #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
22 #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
24 #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
26 #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
28 #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
30 #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
31 typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
33 #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
35 // Comma if nonzero number of arguments
36 #if BOOST_FUNCTION_NUM_ARGS == 0
37 # define BOOST_FUNCTION_COMMA
39 # define BOOST_FUNCTION_COMMA ,
40 #endif // BOOST_FUNCTION_NUM_ARGS > 0
42 // Class names used in this version of the code
43 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
44 #define BOOST_FUNCTION_FUNCTION_INVOKER \
45 BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
46 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
47 BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
48 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
49 BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
50 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
51 BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
52 #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
53 BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
54 #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
55 BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
56 #define BOOST_FUNCTION_MEMBER_INVOKER \
57 BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
58 #define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
59 BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
60 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
61 BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
62 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
63 BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
64 #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
65 BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
66 #define BOOST_FUNCTION_GET_MEMBER_INVOKER \
67 BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
68 #define BOOST_FUNCTION_GET_INVOKER \
69 BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
70 #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
72 #ifndef BOOST_NO_VOID_RETURNS
73 # define BOOST_FUNCTION_VOID_RETURN_TYPE void
74 # define BOOST_FUNCTION_RETURN(X) X
76 # define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable
77 # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
85 typename R BOOST_FUNCTION_COMMA
86 BOOST_FUNCTION_TEMPLATE_PARMS
88 struct BOOST_FUNCTION_FUNCTION_INVOKER
90 static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
93 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
94 return f(BOOST_FUNCTION_ARGS);
100 typename R BOOST_FUNCTION_COMMA
101 BOOST_FUNCTION_TEMPLATE_PARMS
103 struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
105 static BOOST_FUNCTION_VOID_RETURN_TYPE
106 invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
107 BOOST_FUNCTION_PARMS)
110 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
111 BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
116 typename FunctionObj,
117 typename R BOOST_FUNCTION_COMMA
118 BOOST_FUNCTION_TEMPLATE_PARMS
120 struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
122 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
123 BOOST_FUNCTION_PARMS)
127 if (function_allows_small_object_optimization<FunctionObj>::value)
128 f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
130 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
131 return (*f)(BOOST_FUNCTION_ARGS);
136 typename FunctionObj,
137 typename R BOOST_FUNCTION_COMMA
138 BOOST_FUNCTION_TEMPLATE_PARMS
140 struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
142 static BOOST_FUNCTION_VOID_RETURN_TYPE
143 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
144 BOOST_FUNCTION_PARMS)
148 if (function_allows_small_object_optimization<FunctionObj>::value)
149 f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
151 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
152 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
157 typename FunctionObj,
158 typename R BOOST_FUNCTION_COMMA
159 BOOST_FUNCTION_TEMPLATE_PARMS
161 struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
163 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
164 BOOST_FUNCTION_PARMS)
168 reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
169 return (*f)(BOOST_FUNCTION_ARGS);
174 typename FunctionObj,
175 typename R BOOST_FUNCTION_COMMA
176 BOOST_FUNCTION_TEMPLATE_PARMS
178 struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
180 static BOOST_FUNCTION_VOID_RETURN_TYPE
181 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
182 BOOST_FUNCTION_PARMS)
186 reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
187 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
191 #if BOOST_FUNCTION_NUM_ARGS > 0
192 /* Handle invocation of member pointers. */
195 typename R BOOST_FUNCTION_COMMA
196 BOOST_FUNCTION_TEMPLATE_PARMS
198 struct BOOST_FUNCTION_MEMBER_INVOKER
200 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
201 BOOST_FUNCTION_PARMS)
205 reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
206 return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
212 typename R BOOST_FUNCTION_COMMA
213 BOOST_FUNCTION_TEMPLATE_PARMS
215 struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
217 static BOOST_FUNCTION_VOID_RETURN_TYPE
218 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
219 BOOST_FUNCTION_PARMS)
223 reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
224 BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
230 typename FunctionPtr,
231 typename R BOOST_FUNCTION_COMMA
232 BOOST_FUNCTION_TEMPLATE_PARMS
234 struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
236 typedef typename mpl::if_c<(is_void<R>::value),
237 BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
239 R BOOST_FUNCTION_COMMA
240 BOOST_FUNCTION_TEMPLATE_ARGS
242 BOOST_FUNCTION_FUNCTION_INVOKER<
244 R BOOST_FUNCTION_COMMA
245 BOOST_FUNCTION_TEMPLATE_ARGS
251 typename FunctionObj,
252 typename R BOOST_FUNCTION_COMMA
253 BOOST_FUNCTION_TEMPLATE_PARMS
255 struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
257 typedef typename mpl::if_c<(is_void<R>::value),
258 BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
260 R BOOST_FUNCTION_COMMA
261 BOOST_FUNCTION_TEMPLATE_ARGS
263 BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
265 R BOOST_FUNCTION_COMMA
266 BOOST_FUNCTION_TEMPLATE_ARGS
272 typename FunctionObj,
273 typename R BOOST_FUNCTION_COMMA
274 BOOST_FUNCTION_TEMPLATE_PARMS
276 struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
278 typedef typename mpl::if_c<(is_void<R>::value),
279 BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
281 R BOOST_FUNCTION_COMMA
282 BOOST_FUNCTION_TEMPLATE_ARGS
284 BOOST_FUNCTION_FUNCTION_REF_INVOKER<
286 R BOOST_FUNCTION_COMMA
287 BOOST_FUNCTION_TEMPLATE_ARGS
292 #if BOOST_FUNCTION_NUM_ARGS > 0
293 /* Retrieve the appropriate invoker for a member pointer. */
296 typename R BOOST_FUNCTION_COMMA
297 BOOST_FUNCTION_TEMPLATE_PARMS
299 struct BOOST_FUNCTION_GET_MEMBER_INVOKER
301 typedef typename mpl::if_c<(is_void<R>::value),
302 BOOST_FUNCTION_VOID_MEMBER_INVOKER<
304 R BOOST_FUNCTION_COMMA
305 BOOST_FUNCTION_TEMPLATE_ARGS
307 BOOST_FUNCTION_MEMBER_INVOKER<
309 R BOOST_FUNCTION_COMMA
310 BOOST_FUNCTION_TEMPLATE_ARGS
316 /* Given the tag returned by get_function_tag, retrieve the
317 actual invoker that will be used for the given function
320 Each specialization contains an "apply" nested class template
321 that accepts the function object, return type, function
322 argument types, and allocator. The resulting "apply" class
323 contains two typedefs, "invoker_type" and "manager_type",
324 which correspond to the invoker and manager types. */
325 template<typename Tag>
326 struct BOOST_FUNCTION_GET_INVOKER { };
328 /* Retrieve the invoker for a function pointer. */
330 struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
332 template<typename FunctionPtr,
333 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
336 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
338 R BOOST_FUNCTION_COMMA
339 BOOST_FUNCTION_TEMPLATE_ARGS
343 typedef functor_manager<FunctionPtr> manager_type;
346 template<typename FunctionPtr,
347 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
351 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
353 R BOOST_FUNCTION_COMMA
354 BOOST_FUNCTION_TEMPLATE_ARGS
358 typedef functor_manager<FunctionPtr> manager_type;
362 #if BOOST_FUNCTION_NUM_ARGS > 0
363 /* Retrieve the invoker for a member pointer. */
365 struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
367 template<typename MemberPtr,
368 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
371 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
373 R BOOST_FUNCTION_COMMA
374 BOOST_FUNCTION_TEMPLATE_ARGS
378 typedef functor_manager<MemberPtr> manager_type;
381 template<typename MemberPtr,
382 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
386 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
388 R BOOST_FUNCTION_COMMA
389 BOOST_FUNCTION_TEMPLATE_ARGS
393 typedef functor_manager<MemberPtr> manager_type;
398 /* Retrieve the invoker for a function object. */
400 struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
402 template<typename FunctionObj,
403 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
406 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
408 R BOOST_FUNCTION_COMMA
409 BOOST_FUNCTION_TEMPLATE_ARGS
413 typedef functor_manager<FunctionObj> manager_type;
416 template<typename FunctionObj,
417 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
421 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
423 R BOOST_FUNCTION_COMMA
424 BOOST_FUNCTION_TEMPLATE_ARGS
428 typedef functor_manager_a<FunctionObj, Allocator> manager_type;
432 /* Retrieve the invoker for a reference to a function object. */
434 struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
436 template<typename RefWrapper,
437 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
440 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
441 typename RefWrapper::type,
442 R BOOST_FUNCTION_COMMA
443 BOOST_FUNCTION_TEMPLATE_ARGS
447 typedef reference_manager<typename RefWrapper::type> manager_type;
450 template<typename RefWrapper,
451 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
455 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
456 typename RefWrapper::type,
457 R BOOST_FUNCTION_COMMA
458 BOOST_FUNCTION_TEMPLATE_ARGS
462 typedef reference_manager<typename RefWrapper::type> manager_type;
468 * vtable for a specific boost::function instance. This
469 * structure must be an aggregate so that we can use static
470 * initialization in boost::function's assign_to and assign_to_a
471 * members. It therefore cannot have any constructors,
472 * destructors, base classes, etc.
474 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
475 struct BOOST_FUNCTION_VTABLE
477 #ifndef BOOST_NO_VOID_RETURNS
478 typedef R result_type;
480 typedef typename function_return_type<R>::type result_type;
481 #endif // BOOST_NO_VOID_RETURNS
483 typedef result_type (*invoker_type)(function_buffer&
485 BOOST_FUNCTION_TEMPLATE_ARGS);
488 bool assign_to(F f, function_buffer& functor)
490 typedef typename get_function_tag<F>::type tag;
491 return assign_to(f, functor, tag());
493 template<typename F,typename Allocator>
494 bool assign_to_a(F f, function_buffer& functor, Allocator a)
496 typedef typename get_function_tag<F>::type tag;
497 return assign_to_a(f, functor, a, tag());
500 void clear(function_buffer& functor)
503 base.manager(functor, functor, destroy_functor_tag);
508 template<typename FunctionPtr>
510 assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
512 this->clear(functor);
514 // should be a reinterpret cast, but some compilers insist
515 // on giving cv-qualifiers to free functions
516 functor.func_ptr = (void (*)())(f);
522 template<typename FunctionPtr,typename Allocator>
524 assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag)
526 return assign_to(f,functor,function_ptr_tag());
530 #if BOOST_FUNCTION_NUM_ARGS > 0
531 template<typename MemberPtr>
532 bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag)
534 // DPG TBD: Add explicit support for member function
535 // objects, so we invoke through mem_fn() but we retain the
536 // right target_type() values.
538 this->assign_to(mem_fn(f), functor);
544 template<typename MemberPtr,typename Allocator>
545 bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag)
547 // DPG TBD: Add explicit support for member function
548 // objects, so we invoke through mem_fn() but we retain the
549 // right target_type() values.
551 this->assign_to_a(mem_fn(f), functor, a);
557 #endif // BOOST_FUNCTION_NUM_ARGS > 0
560 // Assign to a function object using the small object optimization
561 template<typename FunctionObj>
563 assign_functor(FunctionObj f, function_buffer& functor, mpl::true_)
565 new ((void*)&functor.data) FunctionObj(f);
567 template<typename FunctionObj,typename Allocator>
569 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_)
571 assign_functor(f,functor,mpl::true_());
574 // Assign to a function object allocated on the heap.
575 template<typename FunctionObj>
577 assign_functor(FunctionObj f, function_buffer& functor, mpl::false_)
579 functor.obj_ptr = new FunctionObj(f);
581 template<typename FunctionObj,typename Allocator>
583 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_)
585 typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
586 typedef typename Allocator::template rebind<functor_wrapper_type>::other
587 wrapper_allocator_type;
588 typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
589 wrapper_allocator_type wrapper_allocator(a);
590 wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
591 wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
592 functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
593 functor.obj_ptr = new_f;
596 template<typename FunctionObj>
598 assign_to(FunctionObj f, function_buffer& functor, function_obj_tag)
600 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
601 assign_functor(f, functor,
602 mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
608 template<typename FunctionObj,typename Allocator>
610 assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag)
612 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
613 assign_functor_a(f, functor, a,
614 mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
621 // Reference to a function object
622 template<typename FunctionObj>
624 assign_to(const reference_wrapper<FunctionObj>& f,
625 function_buffer& functor, function_obj_ref_tag)
627 if (!boost::detail::function::has_empty_target(f.get_pointer())) {
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;
636 template<typename FunctionObj,typename Allocator>
638 assign_to_a(const reference_wrapper<FunctionObj>& f,
639 function_buffer& functor, Allocator, function_obj_ref_tag)
641 return assign_to(f,functor,function_obj_ref_tag());
646 invoker_type invoker;
648 } // end namespace function
649 } // end namespace detail
652 typename R BOOST_FUNCTION_COMMA
653 BOOST_FUNCTION_TEMPLATE_PARMS
655 class BOOST_FUNCTION_FUNCTION : public function_base
657 #if BOOST_FUNCTION_NUM_ARGS == 1
659 , public std::unary_function<T0,R>
661 #elif BOOST_FUNCTION_NUM_ARGS == 2
663 , public std::binary_function<T0,T1,R>
669 #ifndef BOOST_NO_VOID_RETURNS
670 typedef R result_type;
672 typedef typename boost::detail::function::function_return_type<R>::type
674 #endif // BOOST_NO_VOID_RETURNS
677 typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
678 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
681 struct clear_type {};
684 BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
686 // add signature for boost::lambda
687 template<typename Args>
690 typedef result_type type;
693 #if BOOST_FUNCTION_NUM_ARGS == 1
694 typedef T0 argument_type;
695 #elif BOOST_FUNCTION_NUM_ARGS == 2
696 typedef T0 first_argument_type;
697 typedef T1 second_argument_type;
700 BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
701 BOOST_FUNCTION_ARG_TYPES
703 typedef BOOST_FUNCTION_FUNCTION self_type;
705 BOOST_FUNCTION_FUNCTION() : function_base() { }
707 // MSVC chokes if the following two constructors are collapsed into
708 // one with a default parameter.
709 template<typename Functor>
710 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
711 #ifndef BOOST_NO_SFINAE
712 ,typename enable_if_c<
713 (boost::type_traits::ice_not<
714 (is_integral<Functor>::value)>::value),
716 #endif // BOOST_NO_SFINAE
722 template<typename Functor,typename Allocator>
723 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
724 #ifndef BOOST_NO_SFINAE
725 ,typename enable_if_c<
726 (boost::type_traits::ice_not<
727 (is_integral<Functor>::value)>::value),
729 #endif // BOOST_NO_SFINAE
733 this->assign_to_a(f,a);
736 #ifndef BOOST_NO_SFINAE
737 BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
739 BOOST_FUNCTION_FUNCTION(int zero) : function_base()
741 BOOST_ASSERT(zero == 0);
745 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
747 this->assign_to_own(f);
750 ~BOOST_FUNCTION_FUNCTION() { clear(); }
752 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
753 // MSVC 6.0 and prior require all definitions to be inline, but
754 // these definitions can become very costly.
755 result_type operator()(BOOST_FUNCTION_PARMS) const
758 boost::throw_exception(bad_function_call());
760 return static_cast<vtable_type*>(vtable)->invoker
761 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
764 result_type operator()(BOOST_FUNCTION_PARMS) const;
767 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
768 // when to use self_type is obnoxious. MSVC cannot handle self_type as
769 // the return type of these assignment operators, but Borland C++ cannot
770 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
772 template<typename Functor>
773 #ifndef BOOST_NO_SFINAE
774 typename enable_if_c<
775 (boost::type_traits::ice_not<
776 (is_integral<Functor>::value)>::value),
777 BOOST_FUNCTION_FUNCTION&>::type
779 BOOST_FUNCTION_FUNCTION&
781 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
792 template<typename Functor,typename Allocator>
793 void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
797 this->assign_to_a(f,a);
804 #ifndef BOOST_NO_SFINAE
805 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
811 BOOST_FUNCTION_FUNCTION& operator=(int zero)
813 BOOST_ASSERT(zero == 0);
819 // Assignment from another BOOST_FUNCTION_FUNCTION
820 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
827 this->assign_to_own(f);
835 void swap(BOOST_FUNCTION_FUNCTION& other)
840 BOOST_FUNCTION_FUNCTION tmp;
841 tmp.move_assign(*this);
842 this->move_assign(other);
843 other.move_assign(tmp);
846 // Clear out a target, if there is one
850 reinterpret_cast<vtable_type*>(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 f.vtable->manager(f.functor, this->functor,
880 boost::detail::function::clone_functor_tag);
884 template<typename Functor>
885 void assign_to(Functor f)
887 using detail::function::vtable_base;
889 typedef typename detail::function::get_function_tag<Functor>::type tag;
890 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
891 typedef typename get_invoker::
892 template apply<Functor, R BOOST_FUNCTION_COMMA
893 BOOST_FUNCTION_TEMPLATE_ARGS>
896 typedef typename handler_type::invoker_type invoker_type;
897 typedef typename handler_type::manager_type manager_type;
899 // Note: it is extremely important that this initialization use
900 // static initialization. Otherwise, we will have a race
901 // condition here in multi-threaded code. See
902 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
903 static vtable_type stored_vtable =
904 { { &manager_type::manage }, &invoker_type::invoke };
906 if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable.base;
910 template<typename Functor,typename Allocator>
911 void assign_to_a(Functor f,Allocator a)
913 using detail::function::vtable_base;
915 typedef typename detail::function::get_function_tag<Functor>::type tag;
916 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
917 typedef typename get_invoker::
918 template apply_a<Functor, R BOOST_FUNCTION_COMMA
919 BOOST_FUNCTION_TEMPLATE_ARGS,
923 typedef typename handler_type::invoker_type invoker_type;
924 typedef typename handler_type::manager_type manager_type;
926 // Note: it is extremely important that this initialization use
927 // static initialization. Otherwise, we will have a race
928 // condition here in multi-threaded code. See
929 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
930 static vtable_type stored_vtable =
931 { { &manager_type::manage }, &invoker_type::invoke };
933 if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable.base;
937 // Moves the value from the specified argument to *this. If the argument
938 // has its function object allocated on the heap, move_assign will pass
939 // its buffer to *this, and set the argument's buffer pointer to NULL.
940 void move_assign(BOOST_FUNCTION_FUNCTION& f)
945 #if !defined(BOOST_NO_EXCEPTIONS)
949 this->vtable = f.vtable;
950 f.vtable->manager(f.functor, this->functor,
951 boost::detail::function::move_functor_tag);
953 #if !defined(BOOST_NO_EXCEPTIONS)
965 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
966 inline void swap(BOOST_FUNCTION_FUNCTION<
967 R BOOST_FUNCTION_COMMA
968 BOOST_FUNCTION_TEMPLATE_ARGS
970 BOOST_FUNCTION_FUNCTION<
971 R BOOST_FUNCTION_COMMA
972 BOOST_FUNCTION_TEMPLATE_ARGS
978 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
979 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
980 typename BOOST_FUNCTION_FUNCTION<
981 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type
982 BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
983 ::operator()(BOOST_FUNCTION_PARMS) const
986 boost::throw_exception(bad_function_call());
988 return reinterpret_cast<const vtable_type*>(vtable)->invoker
989 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
993 // Poison comparisons between boost::function objects of the same type.
994 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
995 void operator==(const BOOST_FUNCTION_FUNCTION<
996 R BOOST_FUNCTION_COMMA
997 BOOST_FUNCTION_TEMPLATE_ARGS>&,
998 const BOOST_FUNCTION_FUNCTION<
999 R BOOST_FUNCTION_COMMA
1000 BOOST_FUNCTION_TEMPLATE_ARGS>&);
1001 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1002 void operator!=(const BOOST_FUNCTION_FUNCTION<
1003 R BOOST_FUNCTION_COMMA
1004 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1005 const BOOST_FUNCTION_FUNCTION<
1006 R BOOST_FUNCTION_COMMA
1007 BOOST_FUNCTION_TEMPLATE_ARGS>& );
1009 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1011 #if BOOST_FUNCTION_NUM_ARGS == 0
1012 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
1014 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
1017 template<typename R BOOST_FUNCTION_COMMA
1018 BOOST_FUNCTION_TEMPLATE_PARMS>
1019 class function<BOOST_FUNCTION_PARTIAL_SPEC>
1020 : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1022 typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
1023 typedef function self_type;
1025 struct clear_type {};
1029 function() : base_type() {}
1031 template<typename Functor>
1033 #ifndef BOOST_NO_SFINAE
1034 ,typename enable_if_c<
1035 (boost::type_traits::ice_not<
1036 (is_integral<Functor>::value)>::value),
1043 template<typename Functor,typename Allocator>
1044 function(Functor f, Allocator a
1045 #ifndef BOOST_NO_SFINAE
1046 ,typename enable_if_c<
1047 (boost::type_traits::ice_not<
1048 (is_integral<Functor>::value)>::value),
1056 #ifndef BOOST_NO_SFINAE
1057 function(clear_type*) : base_type() {}
1060 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1062 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1064 self_type& operator=(const self_type& f)
1066 self_type(f).swap(*this);
1070 template<typename Functor>
1071 #ifndef BOOST_NO_SFINAE
1072 typename enable_if_c<
1073 (boost::type_traits::ice_not<
1074 (is_integral<Functor>::value)>::value),
1079 operator=(Functor f)
1081 self_type(f).swap(*this);
1085 #ifndef BOOST_NO_SFINAE
1086 self_type& operator=(clear_type*)
1093 self_type& operator=(const base_type& f)
1095 self_type(f).swap(*this);
1100 #undef BOOST_FUNCTION_PARTIAL_SPEC
1101 #endif // have partial specialization
1103 } // end namespace boost
1105 // Cleanup after ourselves...
1106 #undef BOOST_FUNCTION_VTABLE
1107 #undef BOOST_FUNCTION_COMMA
1108 #undef BOOST_FUNCTION_FUNCTION
1109 #undef BOOST_FUNCTION_FUNCTION_INVOKER
1110 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
1111 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
1112 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
1113 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
1114 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
1115 #undef BOOST_FUNCTION_MEMBER_INVOKER
1116 #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
1117 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
1118 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
1119 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
1120 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
1121 #undef BOOST_FUNCTION_GET_INVOKER
1122 #undef BOOST_FUNCTION_TEMPLATE_PARMS
1123 #undef BOOST_FUNCTION_TEMPLATE_ARGS
1124 #undef BOOST_FUNCTION_PARMS
1125 #undef BOOST_FUNCTION_PARM
1126 #undef BOOST_FUNCTION_ARGS
1127 #undef BOOST_FUNCTION_ARG_TYPE
1128 #undef BOOST_FUNCTION_ARG_TYPES
1129 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
1130 #undef BOOST_FUNCTION_RETURN
1132 #if defined(BOOST_MSVC)
1133 # pragma warning( pop )