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/core/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 # define BOOST_FUNCTION_ARG(J,I,D) static_cast<BOOST_PP_CAT(T,I)&&>(BOOST_PP_CAT(a,I))
33 # define BOOST_FUNCTION_ARGS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG,BOOST_PP_EMPTY)
36 #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
37 typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
39 #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
41 // Comma if nonzero number of arguments
42 #if BOOST_FUNCTION_NUM_ARGS == 0
43 # define BOOST_FUNCTION_COMMA
45 # define BOOST_FUNCTION_COMMA ,
46 #endif // BOOST_FUNCTION_NUM_ARGS > 0
48 // Class names used in this version of the code
49 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
50 #define BOOST_FUNCTION_FUNCTION_INVOKER \
51 BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
52 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
53 BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
54 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
55 BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
56 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
57 BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
58 #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
59 BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
60 #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
61 BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
62 #define BOOST_FUNCTION_MEMBER_INVOKER \
63 BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
64 #define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
65 BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
66 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
67 BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
68 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
69 BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
70 #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
71 BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
72 #define BOOST_FUNCTION_GET_MEMBER_INVOKER \
73 BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
74 #define BOOST_FUNCTION_GET_INVOKER \
75 BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
76 #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
78 #ifndef BOOST_NO_VOID_RETURNS
79 # define BOOST_FUNCTION_VOID_RETURN_TYPE void
80 # define BOOST_FUNCTION_RETURN(X) X
82 # define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable
83 # define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
91 typename R BOOST_FUNCTION_COMMA
92 BOOST_FUNCTION_TEMPLATE_PARMS
94 struct BOOST_FUNCTION_FUNCTION_INVOKER
96 static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
99 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
100 return f(BOOST_FUNCTION_ARGS);
105 typename FunctionPtr,
106 typename R BOOST_FUNCTION_COMMA
107 BOOST_FUNCTION_TEMPLATE_PARMS
109 struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
111 static BOOST_FUNCTION_VOID_RETURN_TYPE
112 invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
113 BOOST_FUNCTION_PARMS)
116 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
117 BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
122 typename FunctionObj,
123 typename R BOOST_FUNCTION_COMMA
124 BOOST_FUNCTION_TEMPLATE_PARMS
126 struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
128 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
129 BOOST_FUNCTION_PARMS)
133 if (function_allows_small_object_optimization<FunctionObj>::value)
134 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
136 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
137 return (*f)(BOOST_FUNCTION_ARGS);
142 typename FunctionObj,
143 typename R BOOST_FUNCTION_COMMA
144 BOOST_FUNCTION_TEMPLATE_PARMS
146 struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
148 static BOOST_FUNCTION_VOID_RETURN_TYPE
149 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
150 BOOST_FUNCTION_PARMS)
154 if (function_allows_small_object_optimization<FunctionObj>::value)
155 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
157 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
158 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
163 typename FunctionObj,
164 typename R BOOST_FUNCTION_COMMA
165 BOOST_FUNCTION_TEMPLATE_PARMS
167 struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
169 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
170 BOOST_FUNCTION_PARMS)
174 reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
175 return (*f)(BOOST_FUNCTION_ARGS);
180 typename FunctionObj,
181 typename R BOOST_FUNCTION_COMMA
182 BOOST_FUNCTION_TEMPLATE_PARMS
184 struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
186 static BOOST_FUNCTION_VOID_RETURN_TYPE
187 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
188 BOOST_FUNCTION_PARMS)
192 reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
193 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
197 #if BOOST_FUNCTION_NUM_ARGS > 0
198 /* Handle invocation of member pointers. */
201 typename R BOOST_FUNCTION_COMMA
202 BOOST_FUNCTION_TEMPLATE_PARMS
204 struct BOOST_FUNCTION_MEMBER_INVOKER
206 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
207 BOOST_FUNCTION_PARMS)
211 reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
212 return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
218 typename R BOOST_FUNCTION_COMMA
219 BOOST_FUNCTION_TEMPLATE_PARMS
221 struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
223 static BOOST_FUNCTION_VOID_RETURN_TYPE
224 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
225 BOOST_FUNCTION_PARMS)
229 reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
230 BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
236 typename FunctionPtr,
237 typename R BOOST_FUNCTION_COMMA
238 BOOST_FUNCTION_TEMPLATE_PARMS
240 struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
242 typedef typename conditional<(is_void<R>::value),
243 BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
245 R BOOST_FUNCTION_COMMA
246 BOOST_FUNCTION_TEMPLATE_ARGS
248 BOOST_FUNCTION_FUNCTION_INVOKER<
250 R BOOST_FUNCTION_COMMA
251 BOOST_FUNCTION_TEMPLATE_ARGS
257 typename FunctionObj,
258 typename R BOOST_FUNCTION_COMMA
259 BOOST_FUNCTION_TEMPLATE_PARMS
261 struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
263 typedef typename conditional<(is_void<R>::value),
264 BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
266 R BOOST_FUNCTION_COMMA
267 BOOST_FUNCTION_TEMPLATE_ARGS
269 BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
271 R BOOST_FUNCTION_COMMA
272 BOOST_FUNCTION_TEMPLATE_ARGS
278 typename FunctionObj,
279 typename R BOOST_FUNCTION_COMMA
280 BOOST_FUNCTION_TEMPLATE_PARMS
282 struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
284 typedef typename conditional<(is_void<R>::value),
285 BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
287 R BOOST_FUNCTION_COMMA
288 BOOST_FUNCTION_TEMPLATE_ARGS
290 BOOST_FUNCTION_FUNCTION_REF_INVOKER<
292 R BOOST_FUNCTION_COMMA
293 BOOST_FUNCTION_TEMPLATE_ARGS
298 #if BOOST_FUNCTION_NUM_ARGS > 0
299 /* Retrieve the appropriate invoker for a member pointer. */
302 typename R BOOST_FUNCTION_COMMA
303 BOOST_FUNCTION_TEMPLATE_PARMS
305 struct BOOST_FUNCTION_GET_MEMBER_INVOKER
307 typedef typename conditional<(is_void<R>::value),
308 BOOST_FUNCTION_VOID_MEMBER_INVOKER<
310 R BOOST_FUNCTION_COMMA
311 BOOST_FUNCTION_TEMPLATE_ARGS
313 BOOST_FUNCTION_MEMBER_INVOKER<
315 R BOOST_FUNCTION_COMMA
316 BOOST_FUNCTION_TEMPLATE_ARGS
322 /* Given the tag returned by get_function_tag, retrieve the
323 actual invoker that will be used for the given function
326 Each specialization contains an "apply" nested class template
327 that accepts the function object, return type, function
328 argument types, and allocator. The resulting "apply" class
329 contains two typedefs, "invoker_type" and "manager_type",
330 which correspond to the invoker and manager types. */
331 template<typename Tag>
332 struct BOOST_FUNCTION_GET_INVOKER { };
334 /* Retrieve the invoker for a function pointer. */
336 struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
338 template<typename FunctionPtr,
339 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
342 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
344 R BOOST_FUNCTION_COMMA
345 BOOST_FUNCTION_TEMPLATE_ARGS
349 typedef functor_manager<FunctionPtr> manager_type;
352 template<typename FunctionPtr, typename Allocator,
353 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
356 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
358 R BOOST_FUNCTION_COMMA
359 BOOST_FUNCTION_TEMPLATE_ARGS
363 typedef functor_manager<FunctionPtr> manager_type;
367 #if BOOST_FUNCTION_NUM_ARGS > 0
368 /* Retrieve the invoker for a member pointer. */
370 struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
372 template<typename MemberPtr,
373 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
376 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
378 R BOOST_FUNCTION_COMMA
379 BOOST_FUNCTION_TEMPLATE_ARGS
383 typedef functor_manager<MemberPtr> manager_type;
386 template<typename MemberPtr, typename Allocator,
387 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
390 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
392 R BOOST_FUNCTION_COMMA
393 BOOST_FUNCTION_TEMPLATE_ARGS
397 typedef functor_manager<MemberPtr> manager_type;
402 /* Retrieve the invoker for a function object. */
404 struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
406 template<typename FunctionObj,
407 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
410 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
412 R BOOST_FUNCTION_COMMA
413 BOOST_FUNCTION_TEMPLATE_ARGS
417 typedef functor_manager<FunctionObj> manager_type;
420 template<typename FunctionObj, typename Allocator,
421 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
424 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
426 R BOOST_FUNCTION_COMMA
427 BOOST_FUNCTION_TEMPLATE_ARGS
431 typedef functor_manager_a<FunctionObj, Allocator> manager_type;
435 /* Retrieve the invoker for a reference to a function object. */
437 struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
439 template<typename RefWrapper,
440 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
443 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
444 typename RefWrapper::type,
445 R BOOST_FUNCTION_COMMA
446 BOOST_FUNCTION_TEMPLATE_ARGS
450 typedef reference_manager<typename RefWrapper::type> manager_type;
453 template<typename RefWrapper, typename Allocator,
454 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
457 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
458 typename RefWrapper::type,
459 R BOOST_FUNCTION_COMMA
460 BOOST_FUNCTION_TEMPLATE_ARGS
464 typedef reference_manager<typename RefWrapper::type> manager_type;
470 * vtable for a specific boost::function instance. This
471 * structure must be an aggregate so that we can use static
472 * initialization in boost::function's assign_to and assign_to_a
473 * members. It therefore cannot have any constructors,
474 * destructors, base classes, etc.
476 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
477 struct BOOST_FUNCTION_VTABLE
479 #ifndef BOOST_NO_VOID_RETURNS
480 typedef R result_type;
482 typedef typename function_return_type<R>::type result_type;
483 #endif // BOOST_NO_VOID_RETURNS
485 typedef result_type (*invoker_type)(function_buffer&
487 BOOST_FUNCTION_TEMPLATE_ARGS);
490 bool assign_to(F f, function_buffer& functor) const
492 typedef typename get_function_tag<F>::type tag;
493 return assign_to(f, functor, tag());
495 template<typename F,typename Allocator>
496 bool assign_to_a(F f, function_buffer& functor, Allocator a) const
498 typedef typename get_function_tag<F>::type tag;
499 return assign_to_a(f, functor, a, tag());
502 void clear(function_buffer& functor) const
505 base.manager(functor, functor, destroy_functor_tag);
510 template<typename FunctionPtr>
512 assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
514 this->clear(functor);
516 // should be a reinterpret cast, but some compilers insist
517 // on giving cv-qualifiers to free functions
518 functor.members.func_ptr = reinterpret_cast<void (*)()>(f);
524 template<typename FunctionPtr,typename Allocator>
526 assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
528 return assign_to(f,functor,function_ptr_tag());
532 #if BOOST_FUNCTION_NUM_ARGS > 0
533 template<typename MemberPtr>
534 bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
536 // DPG TBD: Add explicit support for member function
537 // objects, so we invoke through mem_fn() but we retain the
538 // right target_type() values.
540 this->assign_to(boost::mem_fn(f), functor);
546 template<typename MemberPtr,typename Allocator>
547 bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const
549 // DPG TBD: Add explicit support for member function
550 // objects, so we invoke through mem_fn() but we retain the
551 // right target_type() values.
553 this->assign_to_a(boost::mem_fn(f), functor, a);
559 #endif // BOOST_FUNCTION_NUM_ARGS > 0
562 // Assign to a function object using the small object optimization
563 template<typename FunctionObj>
565 assign_functor(FunctionObj f, function_buffer& functor, true_type) const
567 new (reinterpret_cast<void*>(functor.data)) FunctionObj(f);
569 template<typename FunctionObj,typename Allocator>
571 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, true_type) const
573 assign_functor(f,functor,true_type());
576 // Assign to a function object allocated on the heap.
577 template<typename FunctionObj>
579 assign_functor(FunctionObj f, function_buffer& functor, false_type) const
581 functor.members.obj_ptr = new FunctionObj(f);
583 template<typename FunctionObj,typename Allocator>
585 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, false_type) const
587 typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
588 #if defined(BOOST_NO_CXX11_ALLOCATOR)
589 typedef typename Allocator::template rebind<functor_wrapper_type>::other
590 wrapper_allocator_type;
591 typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
593 using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
594 using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
596 wrapper_allocator_type wrapper_allocator(a);
597 wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
598 #if defined(BOOST_NO_CXX11_ALLOCATOR)
599 wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
601 std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, functor_wrapper_type(f,a));
603 functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
604 functor.members.obj_ptr = new_f;
607 template<typename FunctionObj>
609 assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
611 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
612 assign_functor(f, functor,
613 integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>());
619 template<typename FunctionObj,typename Allocator>
621 assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
623 if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
624 assign_functor_a(f, functor, a,
625 integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>());
632 // Reference to a function object
633 template<typename FunctionObj>
635 assign_to(const reference_wrapper<FunctionObj>& f,
636 function_buffer& functor, function_obj_ref_tag) const
638 functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer());
639 functor.members.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
640 functor.members.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
643 template<typename FunctionObj,typename Allocator>
645 assign_to_a(const reference_wrapper<FunctionObj>& f,
646 function_buffer& functor, Allocator, function_obj_ref_tag) const
648 return assign_to(f,functor,function_obj_ref_tag());
653 invoker_type invoker;
655 } // end namespace function
656 } // end namespace detail
659 typename R BOOST_FUNCTION_COMMA
660 BOOST_FUNCTION_TEMPLATE_PARMS
662 class BOOST_FUNCTION_FUNCTION : public function_base
665 #ifndef BOOST_NO_VOID_RETURNS
666 typedef R result_type;
668 typedef typename boost::detail::function::function_return_type<R>::type
670 #endif // BOOST_NO_VOID_RETURNS
673 typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
674 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
677 vtable_type* get_vtable() const {
678 return reinterpret_cast<vtable_type*>(
679 reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
682 struct clear_type {};
685 BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
687 // add signature for boost::lambda
688 template<typename Args>
691 typedef result_type type;
694 #if BOOST_FUNCTION_NUM_ARGS == 1
695 typedef T0 argument_type;
696 #elif BOOST_FUNCTION_NUM_ARGS == 2
697 typedef T0 first_argument_type;
698 typedef T1 second_argument_type;
701 BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
702 BOOST_FUNCTION_ARG_TYPES
704 typedef BOOST_FUNCTION_FUNCTION self_type;
706 BOOST_DEFAULTED_FUNCTION(BOOST_FUNCTION_FUNCTION(), : function_base() {})
708 // MSVC chokes if the following two constructors are collapsed into
709 // one with a default parameter.
710 template<typename Functor>
711 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
712 #ifndef BOOST_NO_SFINAE
713 ,typename boost::enable_if_<
714 !(is_integral<Functor>::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 boost::enable_if_<
726 !(is_integral<Functor>::value),
728 #endif // BOOST_NO_SFINAE
732 this->assign_to_a(f,a);
735 #ifndef BOOST_NO_SFINAE
736 BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
738 BOOST_FUNCTION_FUNCTION(int zero) : function_base()
740 BOOST_ASSERT(zero == 0);
744 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
746 this->assign_to_own(f);
749 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
750 BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
752 this->move_assign(f);
756 ~BOOST_FUNCTION_FUNCTION() { clear(); }
758 result_type operator()(BOOST_FUNCTION_PARMS) const
761 boost::throw_exception(bad_function_call());
763 return get_vtable()->invoker
764 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
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 boost::enable_if_<
775 !(is_integral<Functor>::value),
776 BOOST_FUNCTION_FUNCTION&>::type
778 BOOST_FUNCTION_FUNCTION&
780 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
785 } BOOST_CATCH (...) {
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);
798 } BOOST_CATCH (...) {
805 #ifndef BOOST_NO_SFINAE
806 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
812 BOOST_FUNCTION_FUNCTION& operator=(int zero)
814 BOOST_ASSERT(zero == 0);
820 // Assignment from another BOOST_FUNCTION_FUNCTION
821 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
828 this->assign_to_own(f);
829 } BOOST_CATCH (...) {
837 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
838 // Move assignment from another BOOST_FUNCTION_FUNCTION
839 BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
846 this->move_assign(f);
847 } BOOST_CATCH (...) {
856 void swap(BOOST_FUNCTION_FUNCTION& other)
861 BOOST_FUNCTION_FUNCTION tmp;
862 tmp.move_assign(*this);
863 this->move_assign(other);
864 other.move_assign(tmp);
867 // Clear out a target, if there is one
871 if (!this->has_trivial_copy_and_destroy())
872 get_vtable()->clear(this->functor);
877 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
878 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
879 operator bool () const { return !this->empty(); }
886 typedef void (dummy::*safe_bool)();
889 operator safe_bool () const
890 { return (this->empty())? 0 : &dummy::nonnull; }
892 bool operator!() const
893 { return this->empty(); }
897 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
900 this->vtable = f.vtable;
901 if (this->has_trivial_copy_and_destroy())
902 // Don't operate on storage directly since union type doesn't relax
903 // strict aliasing rules, despite of having member char type.
904 std::memcpy(this->functor.data, f.functor.data, sizeof(boost::detail::function::function_buffer));
906 get_vtable()->base.manager(f.functor, this->functor,
907 boost::detail::function::clone_functor_tag);
911 template<typename Functor>
912 void assign_to(Functor f)
914 using boost::detail::function::vtable_base;
916 typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
917 typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
918 typedef typename get_invoker::
919 template apply<Functor, R BOOST_FUNCTION_COMMA
920 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 const vtable_type stored_vtable =
931 { { &manager_type::manage }, &invoker_type::invoke };
933 if (stored_vtable.assign_to(f, functor)) {
934 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
935 // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
936 if (boost::has_trivial_copy_constructor<Functor>::value &&
937 boost::has_trivial_destructor<Functor>::value &&
938 boost::detail::function::function_allows_small_object_optimization<Functor>::value)
939 value |= static_cast<std::size_t>(0x01);
940 vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
945 template<typename Functor,typename Allocator>
946 void assign_to_a(Functor f,Allocator a)
948 using boost::detail::function::vtable_base;
950 typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
951 typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
952 typedef typename get_invoker::
953 template apply_a<Functor, Allocator, R BOOST_FUNCTION_COMMA
954 BOOST_FUNCTION_TEMPLATE_ARGS>
957 typedef typename handler_type::invoker_type invoker_type;
958 typedef typename handler_type::manager_type manager_type;
960 // Note: it is extremely important that this initialization use
961 // static initialization. Otherwise, we will have a race
962 // condition here in multi-threaded code. See
963 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
964 static const vtable_type stored_vtable =
965 { { &manager_type::manage }, &invoker_type::invoke };
967 if (stored_vtable.assign_to_a(f, functor, a)) {
968 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
969 // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
970 if (boost::has_trivial_copy_constructor<Functor>::value &&
971 boost::has_trivial_destructor<Functor>::value &&
972 boost::detail::function::function_allows_small_object_optimization<Functor>::value)
973 value |= static_cast<std::size_t>(0x01);
974 vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
979 // Moves the value from the specified argument to *this. If the argument
980 // has its function object allocated on the heap, move_assign will pass
981 // its buffer to *this, and set the argument's buffer pointer to NULL.
982 void move_assign(BOOST_FUNCTION_FUNCTION& f)
989 this->vtable = f.vtable;
990 if (this->has_trivial_copy_and_destroy())
991 // Don't operate on storage directly since union type doesn't relax
992 // strict aliasing rules, despite of having member char type.
993 std::memcpy(this->functor.data, f.functor.data, sizeof(this->functor.data));
995 get_vtable()->base.manager(f.functor, this->functor,
996 boost::detail::function::move_functor_tag);
1001 } BOOST_CATCH (...) {
1009 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1010 inline void swap(BOOST_FUNCTION_FUNCTION<
1011 R BOOST_FUNCTION_COMMA
1012 BOOST_FUNCTION_TEMPLATE_ARGS
1014 BOOST_FUNCTION_FUNCTION<
1015 R BOOST_FUNCTION_COMMA
1016 BOOST_FUNCTION_TEMPLATE_ARGS
1022 // Poison comparisons between boost::function objects of the same type.
1023 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1024 void operator==(const BOOST_FUNCTION_FUNCTION<
1025 R BOOST_FUNCTION_COMMA
1026 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1027 const BOOST_FUNCTION_FUNCTION<
1028 R BOOST_FUNCTION_COMMA
1029 BOOST_FUNCTION_TEMPLATE_ARGS>&);
1030 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1031 void operator!=(const BOOST_FUNCTION_FUNCTION<
1032 R BOOST_FUNCTION_COMMA
1033 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1034 const BOOST_FUNCTION_FUNCTION<
1035 R BOOST_FUNCTION_COMMA
1036 BOOST_FUNCTION_TEMPLATE_ARGS>& );
1038 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1040 #if BOOST_FUNCTION_NUM_ARGS == 0
1041 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
1043 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_FUNCTION_TEMPLATE_ARGS)
1046 template<typename R BOOST_FUNCTION_COMMA
1047 BOOST_FUNCTION_TEMPLATE_PARMS>
1048 class function<BOOST_FUNCTION_PARTIAL_SPEC>
1049 : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1051 typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
1052 typedef function self_type;
1054 struct clear_type {};
1058 BOOST_DEFAULTED_FUNCTION(function(), : base_type() {})
1060 template<typename Functor>
1062 #ifndef BOOST_NO_SFINAE
1063 ,typename boost::enable_if_<
1064 !(is_integral<Functor>::value),
1071 template<typename Functor,typename Allocator>
1072 function(Functor f, Allocator a
1073 #ifndef BOOST_NO_SFINAE
1074 ,typename boost::enable_if_<
1075 !(is_integral<Functor>::value),
1083 #ifndef BOOST_NO_SFINAE
1084 function(clear_type*) : base_type() {}
1087 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1089 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1091 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1092 // Move constructors
1093 function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
1094 function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
1097 self_type& operator=(const self_type& f)
1099 self_type(f).swap(*this);
1103 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1104 self_type& operator=(self_type&& f)
1106 self_type(static_cast<self_type&&>(f)).swap(*this);
1111 template<typename Functor>
1112 #ifndef BOOST_NO_SFINAE
1113 typename boost::enable_if_<
1114 !(is_integral<Functor>::value),
1119 operator=(Functor f)
1121 self_type(f).swap(*this);
1125 #ifndef BOOST_NO_SFINAE
1126 self_type& operator=(clear_type*)
1133 self_type& operator=(const base_type& f)
1135 self_type(f).swap(*this);
1139 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1140 self_type& operator=(base_type&& f)
1142 self_type(static_cast<base_type&&>(f)).swap(*this);
1148 #undef BOOST_FUNCTION_PARTIAL_SPEC
1149 #endif // have partial specialization
1151 } // end namespace boost
1153 // Cleanup after ourselves...
1154 #undef BOOST_FUNCTION_VTABLE
1155 #undef BOOST_FUNCTION_COMMA
1156 #undef BOOST_FUNCTION_FUNCTION
1157 #undef BOOST_FUNCTION_FUNCTION_INVOKER
1158 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
1159 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
1160 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
1161 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
1162 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
1163 #undef BOOST_FUNCTION_MEMBER_INVOKER
1164 #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
1165 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
1166 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
1167 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
1168 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
1169 #undef BOOST_FUNCTION_GET_INVOKER
1170 #undef BOOST_FUNCTION_TEMPLATE_PARMS
1171 #undef BOOST_FUNCTION_TEMPLATE_ARGS
1172 #undef BOOST_FUNCTION_PARMS
1173 #undef BOOST_FUNCTION_PARM
1174 #ifdef BOOST_FUNCTION_ARG
1175 # undef BOOST_FUNCTION_ARG
1177 #undef BOOST_FUNCTION_ARGS
1178 #undef BOOST_FUNCTION_ARG_TYPE
1179 #undef BOOST_FUNCTION_ARG_TYPES
1180 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
1181 #undef BOOST_FUNCTION_RETURN
1183 #if defined(BOOST_MSVC)
1184 # pragma warning( pop )