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 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
30 # define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
32 # include <boost/move/utility_core.hpp>
33 # define BOOST_FUNCTION_ARG(J,I,D) ::boost::forward< BOOST_PP_CAT(T,I) >(BOOST_PP_CAT(a,I))
34 # define BOOST_FUNCTION_ARGS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG,BOOST_PP_EMPTY)
37 #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
38 typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
40 #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
42 // Comma if nonzero number of arguments
43 #if BOOST_FUNCTION_NUM_ARGS == 0
44 # define BOOST_FUNCTION_COMMA
46 # define BOOST_FUNCTION_COMMA ,
47 #endif // BOOST_FUNCTION_NUM_ARGS > 0
49 // Class names used in this version of the code
50 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
51 #define BOOST_FUNCTION_FUNCTION_INVOKER \
52 BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
53 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
54 BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
55 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
56 BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
57 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
58 BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
59 #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
60 BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
61 #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
62 BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
63 #define BOOST_FUNCTION_MEMBER_INVOKER \
64 BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
65 #define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
66 BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
67 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
68 BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
69 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
70 BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
71 #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
72 BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
73 #define BOOST_FUNCTION_GET_MEMBER_INVOKER \
74 BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
75 #define BOOST_FUNCTION_GET_INVOKER \
76 BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
77 #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
79 #ifndef BOOST_NO_VOID_RETURNS
80 # define BOOST_FUNCTION_VOID_RETURN_TYPE void
81 # define BOOST_FUNCTION_RETURN(X) X
83 # define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable
84 # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
92 typename R BOOST_FUNCTION_COMMA
93 BOOST_FUNCTION_TEMPLATE_PARMS
95 struct BOOST_FUNCTION_FUNCTION_INVOKER
97 static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
100 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
101 return f(BOOST_FUNCTION_ARGS);
106 typename FunctionPtr,
107 typename R BOOST_FUNCTION_COMMA
108 BOOST_FUNCTION_TEMPLATE_PARMS
110 struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
112 static BOOST_FUNCTION_VOID_RETURN_TYPE
113 invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
114 BOOST_FUNCTION_PARMS)
117 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
118 BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
123 typename FunctionObj,
124 typename R BOOST_FUNCTION_COMMA
125 BOOST_FUNCTION_TEMPLATE_PARMS
127 struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
129 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
130 BOOST_FUNCTION_PARMS)
134 if (function_allows_small_object_optimization<FunctionObj>::value)
135 f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
137 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
138 return (*f)(BOOST_FUNCTION_ARGS);
143 typename FunctionObj,
144 typename R BOOST_FUNCTION_COMMA
145 BOOST_FUNCTION_TEMPLATE_PARMS
147 struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
149 static BOOST_FUNCTION_VOID_RETURN_TYPE
150 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
151 BOOST_FUNCTION_PARMS)
155 if (function_allows_small_object_optimization<FunctionObj>::value)
156 f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
158 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
159 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
164 typename FunctionObj,
165 typename R BOOST_FUNCTION_COMMA
166 BOOST_FUNCTION_TEMPLATE_PARMS
168 struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
170 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
171 BOOST_FUNCTION_PARMS)
175 reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
176 return (*f)(BOOST_FUNCTION_ARGS);
181 typename FunctionObj,
182 typename R BOOST_FUNCTION_COMMA
183 BOOST_FUNCTION_TEMPLATE_PARMS
185 struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
187 static BOOST_FUNCTION_VOID_RETURN_TYPE
188 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
189 BOOST_FUNCTION_PARMS)
193 reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
194 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
198 #if BOOST_FUNCTION_NUM_ARGS > 0
199 /* Handle invocation of member pointers. */
202 typename R BOOST_FUNCTION_COMMA
203 BOOST_FUNCTION_TEMPLATE_PARMS
205 struct BOOST_FUNCTION_MEMBER_INVOKER
207 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
208 BOOST_FUNCTION_PARMS)
212 reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
213 return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
219 typename R BOOST_FUNCTION_COMMA
220 BOOST_FUNCTION_TEMPLATE_PARMS
222 struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
224 static BOOST_FUNCTION_VOID_RETURN_TYPE
225 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
226 BOOST_FUNCTION_PARMS)
230 reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
231 BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
237 typename FunctionPtr,
238 typename R BOOST_FUNCTION_COMMA
239 BOOST_FUNCTION_TEMPLATE_PARMS
241 struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
243 typedef typename mpl::if_c<(is_void<R>::value),
244 BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
246 R BOOST_FUNCTION_COMMA
247 BOOST_FUNCTION_TEMPLATE_ARGS
249 BOOST_FUNCTION_FUNCTION_INVOKER<
251 R BOOST_FUNCTION_COMMA
252 BOOST_FUNCTION_TEMPLATE_ARGS
258 typename FunctionObj,
259 typename R BOOST_FUNCTION_COMMA
260 BOOST_FUNCTION_TEMPLATE_PARMS
262 struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
264 typedef typename mpl::if_c<(is_void<R>::value),
265 BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
267 R BOOST_FUNCTION_COMMA
268 BOOST_FUNCTION_TEMPLATE_ARGS
270 BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
272 R BOOST_FUNCTION_COMMA
273 BOOST_FUNCTION_TEMPLATE_ARGS
279 typename FunctionObj,
280 typename R BOOST_FUNCTION_COMMA
281 BOOST_FUNCTION_TEMPLATE_PARMS
283 struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
285 typedef typename mpl::if_c<(is_void<R>::value),
286 BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
288 R BOOST_FUNCTION_COMMA
289 BOOST_FUNCTION_TEMPLATE_ARGS
291 BOOST_FUNCTION_FUNCTION_REF_INVOKER<
293 R BOOST_FUNCTION_COMMA
294 BOOST_FUNCTION_TEMPLATE_ARGS
299 #if BOOST_FUNCTION_NUM_ARGS > 0
300 /* Retrieve the appropriate invoker for a member pointer. */
303 typename R BOOST_FUNCTION_COMMA
304 BOOST_FUNCTION_TEMPLATE_PARMS
306 struct BOOST_FUNCTION_GET_MEMBER_INVOKER
308 typedef typename mpl::if_c<(is_void<R>::value),
309 BOOST_FUNCTION_VOID_MEMBER_INVOKER<
311 R BOOST_FUNCTION_COMMA
312 BOOST_FUNCTION_TEMPLATE_ARGS
314 BOOST_FUNCTION_MEMBER_INVOKER<
316 R BOOST_FUNCTION_COMMA
317 BOOST_FUNCTION_TEMPLATE_ARGS
323 /* Given the tag returned by get_function_tag, retrieve the
324 actual invoker that will be used for the given function
327 Each specialization contains an "apply" nested class template
328 that accepts the function object, return type, function
329 argument types, and allocator. The resulting "apply" class
330 contains two typedefs, "invoker_type" and "manager_type",
331 which correspond to the invoker and manager types. */
332 template<typename Tag>
333 struct BOOST_FUNCTION_GET_INVOKER { };
335 /* Retrieve the invoker for a function pointer. */
337 struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
339 template<typename FunctionPtr,
340 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
343 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
345 R BOOST_FUNCTION_COMMA
346 BOOST_FUNCTION_TEMPLATE_ARGS
350 typedef functor_manager<FunctionPtr> manager_type;
353 template<typename FunctionPtr,
354 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
358 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
360 R BOOST_FUNCTION_COMMA
361 BOOST_FUNCTION_TEMPLATE_ARGS
365 typedef functor_manager<FunctionPtr> manager_type;
369 #if BOOST_FUNCTION_NUM_ARGS > 0
370 /* Retrieve the invoker for a member pointer. */
372 struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
374 template<typename MemberPtr,
375 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
378 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
380 R BOOST_FUNCTION_COMMA
381 BOOST_FUNCTION_TEMPLATE_ARGS
385 typedef functor_manager<MemberPtr> manager_type;
388 template<typename MemberPtr,
389 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
393 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
395 R BOOST_FUNCTION_COMMA
396 BOOST_FUNCTION_TEMPLATE_ARGS
400 typedef functor_manager<MemberPtr> manager_type;
405 /* Retrieve the invoker for a function object. */
407 struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
409 template<typename FunctionObj,
410 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
413 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
415 R BOOST_FUNCTION_COMMA
416 BOOST_FUNCTION_TEMPLATE_ARGS
420 typedef functor_manager<FunctionObj> manager_type;
423 template<typename FunctionObj,
424 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
428 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
430 R BOOST_FUNCTION_COMMA
431 BOOST_FUNCTION_TEMPLATE_ARGS
435 typedef functor_manager_a<FunctionObj, Allocator> manager_type;
439 /* Retrieve the invoker for a reference to a function object. */
441 struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
443 template<typename RefWrapper,
444 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
447 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
448 typename RefWrapper::type,
449 R BOOST_FUNCTION_COMMA
450 BOOST_FUNCTION_TEMPLATE_ARGS
454 typedef reference_manager<typename RefWrapper::type> manager_type;
457 template<typename RefWrapper,
458 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
462 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
463 typename RefWrapper::type,
464 R BOOST_FUNCTION_COMMA
465 BOOST_FUNCTION_TEMPLATE_ARGS
469 typedef reference_manager<typename RefWrapper::type> manager_type;
475 * vtable for a specific boost::function instance. This
476 * structure must be an aggregate so that we can use static
477 * initialization in boost::function's assign_to and assign_to_a
478 * members. It therefore cannot have any constructors,
479 * destructors, base classes, etc.
481 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
482 struct BOOST_FUNCTION_VTABLE
484 #ifndef BOOST_NO_VOID_RETURNS
485 typedef R result_type;
487 typedef typename function_return_type<R>::type result_type;
488 #endif // BOOST_NO_VOID_RETURNS
490 typedef result_type (*invoker_type)(function_buffer&
492 BOOST_FUNCTION_TEMPLATE_ARGS);
495 bool assign_to(F f, function_buffer& functor) const
497 typedef typename get_function_tag<F>::type tag;
498 return assign_to(f, functor, tag());
500 template<typename F,typename Allocator>
501 bool assign_to_a(F f, function_buffer& functor, Allocator a) const
503 typedef typename get_function_tag<F>::type tag;
504 return assign_to_a(f, functor, a, tag());
507 void clear(function_buffer& functor) const
510 base.manager(functor, functor, destroy_functor_tag);
515 template<typename FunctionPtr>
517 assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
519 this->clear(functor);
521 // should be a reinterpret cast, but some compilers insist
522 // on giving cv-qualifiers to free functions
523 functor.func_ptr = reinterpret_cast<void (*)()>(f);
529 template<typename FunctionPtr,typename Allocator>
531 assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
533 return assign_to(f,functor,function_ptr_tag());
537 #if BOOST_FUNCTION_NUM_ARGS > 0
538 template<typename MemberPtr>
539 bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
541 // DPG TBD: Add explicit support for member function
542 // objects, so we invoke through mem_fn() but we retain the
543 // right target_type() values.
545 this->assign_to(boost::mem_fn(f), functor);
551 template<typename MemberPtr,typename Allocator>
552 bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const
554 // DPG TBD: Add explicit support for member function
555 // objects, so we invoke through mem_fn() but we retain the
556 // right target_type() values.
558 this->assign_to_a(boost::mem_fn(f), functor, a);
564 #endif // BOOST_FUNCTION_NUM_ARGS > 0
567 // Assign to a function object using the small object optimization
568 template<typename FunctionObj>
570 assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
572 new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f);
574 template<typename FunctionObj,typename Allocator>
576 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const
578 assign_functor(f,functor,mpl::true_());
581 // Assign to a function object allocated on the heap.
582 template<typename FunctionObj>
584 assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
586 functor.obj_ptr = new FunctionObj(f);
588 template<typename FunctionObj,typename Allocator>
590 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const
592 typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
593 typedef typename Allocator::template rebind<functor_wrapper_type>::other
594 wrapper_allocator_type;
595 typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
596 wrapper_allocator_type wrapper_allocator(a);
597 wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
598 wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
599 functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
600 functor.obj_ptr = new_f;
603 template<typename FunctionObj>
605 assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
607 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
608 assign_functor(f, functor,
609 mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
615 template<typename FunctionObj,typename Allocator>
617 assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
619 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
620 assign_functor_a(f, functor, a,
621 mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
628 // Reference to a function object
629 template<typename FunctionObj>
631 assign_to(const reference_wrapper<FunctionObj>& f,
632 function_buffer& functor, function_obj_ref_tag) const
634 functor.obj_ref.obj_ptr = (void *)(f.get_pointer());
635 functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
636 functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
639 template<typename FunctionObj,typename Allocator>
641 assign_to_a(const reference_wrapper<FunctionObj>& f,
642 function_buffer& functor, Allocator, function_obj_ref_tag) const
644 return assign_to(f,functor,function_obj_ref_tag());
649 invoker_type invoker;
651 } // end namespace function
652 } // end namespace detail
655 typename R BOOST_FUNCTION_COMMA
656 BOOST_FUNCTION_TEMPLATE_PARMS
658 class BOOST_FUNCTION_FUNCTION : public function_base
660 #if BOOST_FUNCTION_NUM_ARGS == 1
662 , public std::unary_function<T0,R>
664 #elif BOOST_FUNCTION_NUM_ARGS == 2
666 , public std::binary_function<T0,T1,R>
672 #ifndef BOOST_NO_VOID_RETURNS
673 typedef R result_type;
675 typedef typename boost::detail::function::function_return_type<R>::type
677 #endif // BOOST_NO_VOID_RETURNS
680 typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
681 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
684 vtable_type* get_vtable() const {
685 return reinterpret_cast<vtable_type*>(
686 reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
689 struct clear_type {};
692 BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
694 // add signature for boost::lambda
695 template<typename Args>
698 typedef result_type type;
701 #if BOOST_FUNCTION_NUM_ARGS == 1
702 typedef T0 argument_type;
703 #elif BOOST_FUNCTION_NUM_ARGS == 2
704 typedef T0 first_argument_type;
705 typedef T1 second_argument_type;
708 BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
709 BOOST_FUNCTION_ARG_TYPES
711 typedef BOOST_FUNCTION_FUNCTION self_type;
713 BOOST_FUNCTION_FUNCTION() : function_base() { }
715 // MSVC chokes if the following two constructors are collapsed into
716 // one with a default parameter.
717 template<typename Functor>
718 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
719 #ifndef BOOST_NO_SFINAE
720 ,typename boost::enable_if_c<
721 !(is_integral<Functor>::value),
723 #endif // BOOST_NO_SFINAE
729 template<typename Functor,typename Allocator>
730 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
731 #ifndef BOOST_NO_SFINAE
732 ,typename boost::enable_if_c<
733 !(is_integral<Functor>::value),
735 #endif // BOOST_NO_SFINAE
739 this->assign_to_a(f,a);
742 #ifndef BOOST_NO_SFINAE
743 BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
745 BOOST_FUNCTION_FUNCTION(int zero) : function_base()
747 BOOST_ASSERT(zero == 0);
751 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
753 this->assign_to_own(f);
756 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
757 BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
759 this->move_assign(f);
763 ~BOOST_FUNCTION_FUNCTION() { clear(); }
765 result_type operator()(BOOST_FUNCTION_PARMS) const
768 boost::throw_exception(bad_function_call());
770 return get_vtable()->invoker
771 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
774 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
775 // when to use self_type is obnoxious. MSVC cannot handle self_type as
776 // the return type of these assignment operators, but Borland C++ cannot
777 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
779 template<typename Functor>
780 #ifndef BOOST_NO_SFINAE
781 typename boost::enable_if_c<
782 !(is_integral<Functor>::value),
783 BOOST_FUNCTION_FUNCTION&>::type
785 BOOST_FUNCTION_FUNCTION&
787 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
792 } BOOST_CATCH (...) {
799 template<typename Functor,typename Allocator>
800 void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
804 this->assign_to_a(f,a);
805 } BOOST_CATCH (...) {
812 #ifndef BOOST_NO_SFINAE
813 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
819 BOOST_FUNCTION_FUNCTION& operator=(int zero)
821 BOOST_ASSERT(zero == 0);
827 // Assignment from another BOOST_FUNCTION_FUNCTION
828 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
835 this->assign_to_own(f);
836 } BOOST_CATCH (...) {
844 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
845 // Move assignment from another BOOST_FUNCTION_FUNCTION
846 BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
854 this->move_assign(f);
855 } BOOST_CATCH (...) {
864 void swap(BOOST_FUNCTION_FUNCTION& other)
869 BOOST_FUNCTION_FUNCTION tmp;
870 tmp.move_assign(*this);
871 this->move_assign(other);
872 other.move_assign(tmp);
875 // Clear out a target, if there is one
879 if (!this->has_trivial_copy_and_destroy())
880 get_vtable()->clear(this->functor);
885 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
886 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
887 operator bool () const { return !this->empty(); }
894 typedef void (dummy::*safe_bool)();
897 operator safe_bool () const
898 { return (this->empty())? 0 : &dummy::nonnull; }
900 bool operator!() const
901 { return this->empty(); }
905 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
908 this->vtable = f.vtable;
909 if (this->has_trivial_copy_and_destroy())
910 this->functor = f.functor;
912 get_vtable()->base.manager(f.functor, this->functor,
913 boost::detail::function::clone_functor_tag);
917 template<typename Functor>
918 void assign_to(Functor f)
920 using boost::detail::function::vtable_base;
922 typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
923 typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
924 typedef typename get_invoker::
925 template apply<Functor, R BOOST_FUNCTION_COMMA
926 BOOST_FUNCTION_TEMPLATE_ARGS>
929 typedef typename handler_type::invoker_type invoker_type;
930 typedef typename handler_type::manager_type manager_type;
932 // Note: it is extremely important that this initialization use
933 // static initialization. Otherwise, we will have a race
934 // condition here in multi-threaded code. See
935 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
936 static const vtable_type stored_vtable =
937 { { &manager_type::manage }, &invoker_type::invoke };
939 if (stored_vtable.assign_to(f, functor)) {
940 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
941 // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
942 if (boost::has_trivial_copy_constructor<Functor>::value &&
943 boost::has_trivial_destructor<Functor>::value &&
944 boost::detail::function::function_allows_small_object_optimization<Functor>::value)
945 value |= static_cast<std::size_t>(0x01);
946 vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
951 template<typename Functor,typename Allocator>
952 void assign_to_a(Functor f,Allocator a)
954 using boost::detail::function::vtable_base;
956 typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
957 typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
958 typedef typename get_invoker::
959 template apply_a<Functor, R BOOST_FUNCTION_COMMA
960 BOOST_FUNCTION_TEMPLATE_ARGS,
964 typedef typename handler_type::invoker_type invoker_type;
965 typedef typename handler_type::manager_type manager_type;
967 // Note: it is extremely important that this initialization use
968 // static initialization. Otherwise, we will have a race
969 // condition here in multi-threaded code. See
970 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
971 static const vtable_type stored_vtable =
972 { { &manager_type::manage }, &invoker_type::invoke };
974 if (stored_vtable.assign_to_a(f, functor, a)) {
975 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
976 // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
977 if (boost::has_trivial_copy_constructor<Functor>::value &&
978 boost::has_trivial_destructor<Functor>::value &&
979 boost::detail::function::function_allows_small_object_optimization<Functor>::value)
980 value |= static_cast<std::size_t>(0x01);
981 vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
986 // Moves the value from the specified argument to *this. If the argument
987 // has its function object allocated on the heap, move_assign will pass
988 // its buffer to *this, and set the argument's buffer pointer to NULL.
989 void move_assign(BOOST_FUNCTION_FUNCTION& f)
996 this->vtable = f.vtable;
997 if (this->has_trivial_copy_and_destroy())
998 this->functor = f.functor;
1000 get_vtable()->base.manager(f.functor, this->functor,
1001 boost::detail::function::move_functor_tag);
1006 } BOOST_CATCH (...) {
1014 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1015 inline void swap(BOOST_FUNCTION_FUNCTION<
1016 R BOOST_FUNCTION_COMMA
1017 BOOST_FUNCTION_TEMPLATE_ARGS
1019 BOOST_FUNCTION_FUNCTION<
1020 R BOOST_FUNCTION_COMMA
1021 BOOST_FUNCTION_TEMPLATE_ARGS
1027 // Poison comparisons between boost::function objects of the same type.
1028 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1029 void operator==(const BOOST_FUNCTION_FUNCTION<
1030 R BOOST_FUNCTION_COMMA
1031 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1032 const BOOST_FUNCTION_FUNCTION<
1033 R BOOST_FUNCTION_COMMA
1034 BOOST_FUNCTION_TEMPLATE_ARGS>&);
1035 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1036 void operator!=(const BOOST_FUNCTION_FUNCTION<
1037 R BOOST_FUNCTION_COMMA
1038 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1039 const BOOST_FUNCTION_FUNCTION<
1040 R BOOST_FUNCTION_COMMA
1041 BOOST_FUNCTION_TEMPLATE_ARGS>& );
1043 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1045 #if BOOST_FUNCTION_NUM_ARGS == 0
1046 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
1048 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
1051 template<typename R BOOST_FUNCTION_COMMA
1052 BOOST_FUNCTION_TEMPLATE_PARMS>
1053 class function<BOOST_FUNCTION_PARTIAL_SPEC>
1054 : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1056 typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
1057 typedef function self_type;
1059 struct clear_type {};
1063 function() : base_type() {}
1065 template<typename Functor>
1067 #ifndef BOOST_NO_SFINAE
1068 ,typename boost::enable_if_c<
1069 !(is_integral<Functor>::value),
1076 template<typename Functor,typename Allocator>
1077 function(Functor f, Allocator a
1078 #ifndef BOOST_NO_SFINAE
1079 ,typename boost::enable_if_c<
1080 !(is_integral<Functor>::value),
1088 #ifndef BOOST_NO_SFINAE
1089 function(clear_type*) : base_type() {}
1092 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1094 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1096 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1097 // Move constructors
1098 function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
1099 function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
1102 self_type& operator=(const self_type& f)
1104 self_type(f).swap(*this);
1108 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1109 self_type& operator=(self_type&& f)
1111 self_type(static_cast<self_type&&>(f)).swap(*this);
1116 template<typename Functor>
1117 #ifndef BOOST_NO_SFINAE
1118 typename boost::enable_if_c<
1119 !(is_integral<Functor>::value),
1124 operator=(Functor f)
1126 self_type(f).swap(*this);
1130 #ifndef BOOST_NO_SFINAE
1131 self_type& operator=(clear_type*)
1138 self_type& operator=(const base_type& f)
1140 self_type(f).swap(*this);
1144 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1145 self_type& operator=(base_type&& f)
1147 self_type(static_cast<base_type&&>(f)).swap(*this);
1153 #undef BOOST_FUNCTION_PARTIAL_SPEC
1154 #endif // have partial specialization
1156 } // end namespace boost
1158 // Cleanup after ourselves...
1159 #undef BOOST_FUNCTION_VTABLE
1160 #undef BOOST_FUNCTION_COMMA
1161 #undef BOOST_FUNCTION_FUNCTION
1162 #undef BOOST_FUNCTION_FUNCTION_INVOKER
1163 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
1164 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
1165 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
1166 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
1167 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
1168 #undef BOOST_FUNCTION_MEMBER_INVOKER
1169 #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
1170 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
1171 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
1172 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
1173 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
1174 #undef BOOST_FUNCTION_GET_INVOKER
1175 #undef BOOST_FUNCTION_TEMPLATE_PARMS
1176 #undef BOOST_FUNCTION_TEMPLATE_ARGS
1177 #undef BOOST_FUNCTION_PARMS
1178 #undef BOOST_FUNCTION_PARM
1179 #ifdef BOOST_FUNCTION_ARG
1180 # undef BOOST_FUNCTION_ARG
1182 #undef BOOST_FUNCTION_ARGS
1183 #undef BOOST_FUNCTION_ARG_TYPE
1184 #undef BOOST_FUNCTION_ARG_TYPES
1185 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
1186 #undef BOOST_FUNCTION_RETURN
1188 #if defined(BOOST_MSVC)
1189 # pragma warning( pop )