1 // Boost.Function library
3 // Copyright Douglas Gregor 2001-2003. Use, modification and
4 // distribution is subject to the Boost Software License, Version
5 // 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
8 // For more information, see http://www.boost.org
10 // Note: this header is a header template and must NOT have multiple-inclusion
12 #include <boost/function/detail/prologue.hpp>
14 #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
16 #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
18 #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
20 #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
22 #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
24 #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
25 typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(arg, BOOST_PP_CAT(BOOST_PP_INC(I),_type));
27 #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
29 // Type of the default allocator
30 #ifndef BOOST_NO_STD_ALLOCATOR
31 # define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
33 # define BOOST_FUNCTION_DEFAULT_ALLOCATOR int
34 #endif // BOOST_NO_STD_ALLOCATOR
36 // Comma if nonzero number of arguments
37 #if BOOST_FUNCTION_NUM_ARGS == 0
38 # define BOOST_FUNCTION_COMMA
40 # define BOOST_FUNCTION_COMMA ,
41 #endif // BOOST_FUNCTION_NUM_ARGS > 0
43 // Class names used in this version of the code
44 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
45 #define BOOST_FUNCTION_FUNCTION_INVOKER \
46 BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
47 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
48 BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
49 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
50 BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
51 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
52 BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
53 #define BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER \
54 BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
55 #define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \
56 BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
57 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
58 BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
59 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
60 BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
61 #define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \
62 BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
69 typename R BOOST_FUNCTION_COMMA
70 BOOST_FUNCTION_TEMPLATE_PARMS
72 struct BOOST_FUNCTION_FUNCTION_INVOKER
74 static R invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
77 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
78 return f(BOOST_FUNCTION_ARGS);
84 typename R BOOST_FUNCTION_COMMA
85 BOOST_FUNCTION_TEMPLATE_PARMS
87 struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
89 static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
93 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
94 f(BOOST_FUNCTION_ARGS);
100 typename FunctionObj,
101 typename R BOOST_FUNCTION_COMMA
102 BOOST_FUNCTION_TEMPLATE_PARMS
104 struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
106 static R invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
107 BOOST_FUNCTION_PARMS)
110 FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
111 return (*f)(BOOST_FUNCTION_ARGS);
116 typename FunctionObj,
117 typename R BOOST_FUNCTION_COMMA
118 BOOST_FUNCTION_TEMPLATE_PARMS
120 struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
122 static unusable invoke(any_pointer function_obj_ptr
124 BOOST_FUNCTION_PARMS)
127 FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
128 (*f)(BOOST_FUNCTION_ARGS);
134 typename FunctionObj,
135 typename R BOOST_FUNCTION_COMMA
136 BOOST_FUNCTION_TEMPLATE_PARMS
138 struct BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
140 static R invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
142 FunctionObj f = FunctionObj();
143 return f(BOOST_FUNCTION_ARGS);
148 typename FunctionObj,
149 typename R BOOST_FUNCTION_COMMA
150 BOOST_FUNCTION_TEMPLATE_PARMS
152 struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
154 static unusable invoke(any_pointer BOOST_FUNCTION_COMMA
155 BOOST_FUNCTION_PARMS)
158 FunctionObj f = FunctionObj();
159 f(BOOST_FUNCTION_ARGS);
165 typename FunctionPtr,
166 typename R BOOST_FUNCTION_COMMA
167 BOOST_FUNCTION_TEMPLATE_PARMS
169 struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
171 typedef typename ct_if<(is_void<R>::value),
172 BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
174 R BOOST_FUNCTION_COMMA
175 BOOST_FUNCTION_TEMPLATE_ARGS
177 BOOST_FUNCTION_FUNCTION_INVOKER<
179 R BOOST_FUNCTION_COMMA
180 BOOST_FUNCTION_TEMPLATE_ARGS
186 typename FunctionObj,
187 typename R BOOST_FUNCTION_COMMA
188 BOOST_FUNCTION_TEMPLATE_PARMS
190 struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
192 typedef typename ct_if<(is_void<R>::value),
193 BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
195 R BOOST_FUNCTION_COMMA
196 BOOST_FUNCTION_TEMPLATE_ARGS
198 BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
200 R BOOST_FUNCTION_COMMA
201 BOOST_FUNCTION_TEMPLATE_ARGS
207 typename FunctionObj,
208 typename R BOOST_FUNCTION_COMMA
209 BOOST_FUNCTION_TEMPLATE_PARMS
211 struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
213 typedef typename ct_if<(is_void<R>::value),
214 BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER<
216 R BOOST_FUNCTION_COMMA
217 BOOST_FUNCTION_TEMPLATE_ARGS
219 BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER<
221 R BOOST_FUNCTION_COMMA
222 BOOST_FUNCTION_TEMPLATE_ARGS
227 } // end namespace function
228 } // end namespace detail
231 typename R BOOST_FUNCTION_COMMA
232 BOOST_FUNCTION_TEMPLATE_PARMS,
233 typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
235 class BOOST_FUNCTION_FUNCTION : public function_base
238 typedef typename detail::function::function_return_type<R>::type
239 internal_result_type;
242 struct clear_type {};
245 BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
247 // add signature for boost::lambda
248 template<typename Args>
251 typedef internal_result_type type;
254 #if BOOST_FUNCTION_NUM_ARGS == 1
255 typedef T0 argument_type;
256 #elif BOOST_FUNCTION_NUM_ARGS == 2
257 typedef T0 first_argument_type;
258 typedef T1 second_argument_type;
261 BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
262 BOOST_FUNCTION_ARG_TYPES
264 #ifndef BOOST_NO_VOID_RETURNS
265 typedef R result_type;
267 typedef internal_result_type result_type;
268 #endif // BOOST_NO_VOID_RETURNS
269 typedef Allocator allocator_type;
270 typedef BOOST_FUNCTION_FUNCTION self_type;
272 BOOST_FUNCTION_FUNCTION() : function_base()
275 // MSVC chokes if the following two constructors are collapsed into
276 // one with a default parameter.
277 template<typename Functor>
278 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
279 #ifndef BOOST_NO_SFINAE
280 ,typename enable_if_c<
281 (::boost::type_traits::ice_not<
282 (is_integral<Functor>::value)>::value),
284 #endif // BOOST_NO_SFINAE
292 #ifndef BOOST_NO_SFINAE
293 BOOST_FUNCTION_FUNCTION(clear_type*) : function_base(), invoker(0) {}
295 BOOST_FUNCTION_FUNCTION(int zero) : function_base(), invoker(0)
297 BOOST_ASSERT(zero == 0);
301 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
305 this->assign_to_own(f);
308 ~BOOST_FUNCTION_FUNCTION() { clear(); }
310 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
311 // MSVC 6.0 and prior require all definitions to be inline, but
312 // these definitions can become very costly.
313 result_type operator()(BOOST_FUNCTION_PARMS) const
316 boost::throw_exception(bad_function_call());
318 internal_result_type result = invoker(this->functor
320 BOOST_FUNCTION_ARGS);
322 #ifndef BOOST_NO_VOID_RETURNS
323 return static_cast<result_type>(result);
326 #endif // BOOST_NO_VOID_RETURNS
329 result_type operator()(BOOST_FUNCTION_PARMS) const;
332 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
333 // when to use self_type is obnoxious. MSVC cannot handle self_type as
334 // the return type of these assignment operators, but Borland C++ cannot
335 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
337 template<typename Functor>
338 #ifndef BOOST_NO_SFINAE
339 typename enable_if_c<
340 (::boost::type_traits::ice_not<
341 (is_integral<Functor>::value)>::value),
342 BOOST_FUNCTION_FUNCTION&>::type
344 BOOST_FUNCTION_FUNCTION&
346 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
348 self_type(f).swap(*this);
352 #ifndef BOOST_NO_SFINAE
353 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
359 BOOST_FUNCTION_FUNCTION& operator=(int zero)
361 BOOST_ASSERT(zero == 0);
367 // Assignment from another BOOST_FUNCTION_FUNCTION
368 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
373 self_type(f).swap(*this);
377 void swap(BOOST_FUNCTION_FUNCTION& other)
382 std::swap(this->manager, other.manager);
383 std::swap(this->functor, other.functor);
384 std::swap(invoker, other.invoker);
387 // Clear out a target, if there is one
391 function_base::functor =
392 this->manager(this->functor, detail::function::destroy_functor_tag);
399 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
400 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
401 operator bool () const { return !this->empty(); }
408 typedef void (dummy::*safe_bool)();
411 operator safe_bool () const
412 { return (this->empty())? 0 : &dummy::nonnull; }
414 bool operator!() const
415 { return this->empty(); }
419 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
423 this->manager = f.manager;
425 f.manager(f.functor, detail::function::clone_functor_tag);
429 template<typename Functor>
430 void assign_to(Functor f)
432 typedef typename detail::function::get_function_tag<Functor>::type tag;
433 this->assign_to(f, tag());
436 template<typename FunctionPtr>
437 void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
442 typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
444 R BOOST_FUNCTION_COMMA
445 BOOST_FUNCTION_TEMPLATE_ARGS
449 invoker = &actual_invoker_type::invoke;
451 &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
453 this->manager(detail::function::make_any_pointer(
454 // should be a reinterpret cast, but some compilers
455 // insist on giving cv-qualifiers to free functions
458 detail::function::clone_functor_tag);
462 #if BOOST_FUNCTION_NUM_ARGS > 0
463 template<typename MemberPtr>
464 void assign_to(MemberPtr f, detail::function::member_ptr_tag)
466 this->assign_to(mem_fn(f));
468 #endif // BOOST_FUNCTION_NUM_ARGS > 0
470 template<typename FunctionObj>
471 void assign_to(FunctionObj f, detail::function::function_obj_tag)
473 if (!detail::function::has_empty_target(addressof(f))) {
475 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
477 R BOOST_FUNCTION_COMMA
478 BOOST_FUNCTION_TEMPLATE_ARGS
482 invoker = &actual_invoker_type::invoke;
483 this->manager = &detail::function::functor_manager<
484 FunctionObj, Allocator>::manage;
485 #ifndef BOOST_NO_STD_ALLOCATOR
486 typedef typename Allocator::template rebind<FunctionObj>::other
487 rebound_allocator_type;
488 typedef typename rebound_allocator_type::pointer pointer_type;
489 rebound_allocator_type allocator;
490 pointer_type copy = allocator.allocate(1);
491 allocator.construct(copy, f);
493 // Get back to the original pointer type
494 FunctionObj* new_f = static_cast<FunctionObj*>(copy);
496 FunctionObj* new_f = new FunctionObj(f);
497 #endif // BOOST_NO_STD_ALLOCATOR
499 detail::function::make_any_pointer(static_cast<void*>(new_f));
503 template<typename FunctionObj>
504 void assign_to(const reference_wrapper<FunctionObj>& f,
505 detail::function::function_obj_ref_tag)
507 if (!detail::function::has_empty_target(f.get_pointer())) {
509 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
511 R BOOST_FUNCTION_COMMA
512 BOOST_FUNCTION_TEMPLATE_ARGS
516 invoker = &actual_invoker_type::invoke;
517 this->manager = &detail::function::trivial_manager<FunctionObj>::get;
520 detail::function::make_any_pointer(
521 const_cast<FunctionObj*>(f.get_pointer())),
522 detail::function::clone_functor_tag);
526 template<typename FunctionObj>
527 void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
530 typename detail::function::
531 BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
533 R BOOST_FUNCTION_COMMA
534 BOOST_FUNCTION_TEMPLATE_ARGS
537 invoker = &actual_invoker_type::invoke;
538 this->manager = &detail::function::trivial_manager<FunctionObj>::get;
539 this->functor = detail::function::make_any_pointer(this);
542 typedef internal_result_type (*invoker_type)(detail::function::any_pointer
544 BOOST_FUNCTION_TEMPLATE_ARGS);
546 invoker_type invoker;
549 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
551 inline void swap(BOOST_FUNCTION_FUNCTION<
552 R BOOST_FUNCTION_COMMA
553 BOOST_FUNCTION_TEMPLATE_ARGS ,
556 BOOST_FUNCTION_FUNCTION<
557 R BOOST_FUNCTION_COMMA
558 BOOST_FUNCTION_TEMPLATE_ARGS,
565 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
566 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
568 typename BOOST_FUNCTION_FUNCTION<
569 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
570 Allocator>::result_type
571 BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
574 ::operator()(BOOST_FUNCTION_PARMS) const
577 boost::throw_exception(bad_function_call());
579 internal_result_type result = invoker(this->functor
581 BOOST_FUNCTION_ARGS);
583 # ifndef BOOST_NO_VOID_RETURNS
584 return static_cast<result_type>(result);
587 # endif // BOOST_NO_VOID_RETURNS
591 // Poison comparisons between boost::function objects of the same type.
592 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
594 void operator==(const BOOST_FUNCTION_FUNCTION<
595 R BOOST_FUNCTION_COMMA
596 BOOST_FUNCTION_TEMPLATE_ARGS ,
598 const BOOST_FUNCTION_FUNCTION<
599 R BOOST_FUNCTION_COMMA
600 BOOST_FUNCTION_TEMPLATE_ARGS ,
602 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
604 void operator!=(const BOOST_FUNCTION_FUNCTION<
605 R BOOST_FUNCTION_COMMA
606 BOOST_FUNCTION_TEMPLATE_ARGS ,
608 const BOOST_FUNCTION_FUNCTION<
609 R BOOST_FUNCTION_COMMA
610 BOOST_FUNCTION_TEMPLATE_ARGS ,
613 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
615 #if BOOST_FUNCTION_NUM_ARGS == 0
616 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
618 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
621 template<typename R BOOST_FUNCTION_COMMA
622 BOOST_FUNCTION_TEMPLATE_PARMS,
624 class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
625 : public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
626 BOOST_FUNCTION_COMMA Allocator>
628 typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
629 BOOST_FUNCTION_COMMA Allocator> base_type;
630 typedef function self_type;
632 struct clear_type {};
635 typedef typename base_type::allocator_type allocator_type;
637 function() : base_type() {}
639 template<typename Functor>
641 #ifndef BOOST_NO_SFINAE
642 ,typename enable_if_c<
643 (::boost::type_traits::ice_not<
644 (is_integral<Functor>::value)>::value),
652 #ifndef BOOST_NO_SFINAE
653 function(clear_type*) : base_type() {}
656 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
658 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
660 self_type& operator=(const self_type& f)
662 self_type(f).swap(*this);
666 template<typename Functor>
667 #ifndef BOOST_NO_SFINAE
668 typename enable_if_c<
669 (::boost::type_traits::ice_not<
670 (is_integral<Functor>::value)>::value),
677 self_type(f).swap(*this);
681 #ifndef BOOST_NO_SFINAE
682 self_type& operator=(clear_type*)
689 self_type& operator=(const base_type& f)
691 self_type(f).swap(*this);
696 #undef BOOST_FUNCTION_PARTIAL_SPEC
697 #endif // have partial specialization
699 } // end namespace boost
701 // Cleanup after ourselves...
702 #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
703 #undef BOOST_FUNCTION_COMMA
704 #undef BOOST_FUNCTION_FUNCTION
705 #undef BOOST_FUNCTION_FUNCTION_INVOKER
706 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
707 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
708 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
709 #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
710 #undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
711 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
712 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
713 #undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
714 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
715 #undef BOOST_FUNCTION_TEMPLATE_PARMS
716 #undef BOOST_FUNCTION_TEMPLATE_ARGS
717 #undef BOOST_FUNCTION_PARMS
718 #undef BOOST_FUNCTION_PARM
719 #undef BOOST_FUNCTION_ARGS
720 #undef BOOST_FUNCTION_ARG_TYPE
721 #undef BOOST_FUNCTION_ARG_TYPES