1 // Boost.Function library
3 // Copyright Doug 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 result_type operator()(BOOST_FUNCTION_PARMS) const
313 boost::throw_exception(bad_function_call());
315 internal_result_type result = invoker(this->functor
317 BOOST_FUNCTION_ARGS);
319 #ifndef BOOST_NO_VOID_RETURNS
320 return static_cast<result_type>(result);
323 #endif // BOOST_NO_VOID_RETURNS
326 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
327 // when to use self_type is obnoxious. MSVC cannot handle self_type as
328 // the return type of these assignment operators, but Borland C++ cannot
329 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
331 template<typename Functor>
332 #ifndef BOOST_NO_SFINAE
333 typename enable_if_c<
334 (::boost::type_traits::ice_not<
335 (is_integral<Functor>::value)>::value),
336 BOOST_FUNCTION_FUNCTION&>::type
338 BOOST_FUNCTION_FUNCTION&
340 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
342 self_type(f).swap(*this);
346 #ifndef BOOST_NO_SFINAE
347 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
353 BOOST_FUNCTION_FUNCTION& operator=(int zero)
355 BOOST_ASSERT(zero == 0);
361 // Assignment from another BOOST_FUNCTION_FUNCTION
362 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
367 self_type(f).swap(*this);
371 void swap(BOOST_FUNCTION_FUNCTION& other)
376 std::swap(this->manager, other.manager);
377 std::swap(this->functor, other.functor);
378 std::swap(invoker, other.invoker);
381 // Clear out a target, if there is one
385 function_base::functor =
386 this->manager(this->functor, detail::function::destroy_functor_tag);
393 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
394 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
395 operator bool () const { return !this->empty(); }
402 typedef void (dummy::*safe_bool)();
405 operator safe_bool () const
406 { return (this->empty())? 0 : &dummy::nonnull; }
408 bool operator!() const
409 { return this->empty(); }
413 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
417 this->manager = f.manager;
419 f.manager(f.functor, detail::function::clone_functor_tag);
423 template<typename Functor>
424 void assign_to(Functor f)
426 typedef typename detail::function::get_function_tag<Functor>::type tag;
427 this->assign_to(f, tag());
430 template<typename FunctionPtr>
431 void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
436 typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
438 R BOOST_FUNCTION_COMMA
439 BOOST_FUNCTION_TEMPLATE_ARGS
443 invoker = &invoker_type::invoke;
445 &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
447 this->manager(detail::function::make_any_pointer(
448 // should be a reinterpret cast, but some compilers
449 // insist on giving cv-qualifiers to free functions
452 detail::function::clone_functor_tag);
456 #if BOOST_FUNCTION_NUM_ARGS > 0
457 template<typename MemberPtr>
458 void assign_to(MemberPtr f, detail::function::member_ptr_tag)
460 this->assign_to(mem_fn(f));
462 #endif // BOOST_FUNCTION_NUM_ARGS > 0
464 template<typename FunctionObj>
465 void assign_to(FunctionObj f, detail::function::function_obj_tag)
467 if (!detail::function::has_empty_target(addressof(f))) {
469 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
471 R BOOST_FUNCTION_COMMA
472 BOOST_FUNCTION_TEMPLATE_ARGS
476 invoker = &invoker_type::invoke;
477 this->manager = &detail::function::functor_manager<
478 FunctionObj, Allocator>::manage;
479 #ifndef BOOST_NO_STD_ALLOCATOR
480 typedef typename Allocator::template rebind<FunctionObj>::other
482 typedef typename allocator_type::pointer pointer_type;
483 allocator_type allocator;
484 pointer_type copy = allocator.allocate(1);
485 allocator.construct(copy, f);
487 // Get back to the original pointer type
488 FunctionObj* new_f = static_cast<FunctionObj*>(copy);
490 FunctionObj* new_f = new FunctionObj(f);
491 #endif // BOOST_NO_STD_ALLOCATOR
493 detail::function::make_any_pointer(static_cast<void*>(new_f));
497 template<typename FunctionObj>
498 void assign_to(const reference_wrapper<FunctionObj>& f,
499 detail::function::function_obj_ref_tag)
501 if (!detail::function::has_empty_target(f.get_pointer())) {
503 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
505 R BOOST_FUNCTION_COMMA
506 BOOST_FUNCTION_TEMPLATE_ARGS
510 invoker = &invoker_type::invoke;
511 this->manager = &detail::function::trivial_manager;
514 detail::function::make_any_pointer(
515 const_cast<FunctionObj*>(f.get_pointer())),
516 detail::function::clone_functor_tag);
520 template<typename FunctionObj>
521 void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
524 typename detail::function::
525 BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
527 R BOOST_FUNCTION_COMMA
528 BOOST_FUNCTION_TEMPLATE_ARGS
531 invoker = &invoker_type::invoke;
532 this->manager = &detail::function::trivial_manager;
533 this->functor = detail::function::make_any_pointer(this);
536 typedef internal_result_type (*invoker_type)(detail::function::any_pointer
538 BOOST_FUNCTION_TEMPLATE_ARGS);
540 invoker_type invoker;
543 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
545 inline void swap(BOOST_FUNCTION_FUNCTION<
546 R BOOST_FUNCTION_COMMA
547 BOOST_FUNCTION_TEMPLATE_ARGS ,
550 BOOST_FUNCTION_FUNCTION<
551 R BOOST_FUNCTION_COMMA
552 BOOST_FUNCTION_TEMPLATE_ARGS,
559 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
561 #if BOOST_FUNCTION_NUM_ARGS == 0
562 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
564 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
567 template<typename R BOOST_FUNCTION_COMMA
568 BOOST_FUNCTION_TEMPLATE_PARMS,
570 class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
571 : public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
572 BOOST_FUNCTION_COMMA Allocator>
574 typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
575 BOOST_FUNCTION_COMMA Allocator> base_type;
576 typedef function self_type;
578 struct clear_type {};
581 typedef typename base_type::allocator_type allocator_type;
583 function() : base_type() {}
585 template<typename Functor>
587 #ifndef BOOST_NO_SFINAE
588 ,typename enable_if_c<
589 (::boost::type_traits::ice_not<
590 (is_integral<Functor>::value)>::value),
598 #ifndef BOOST_NO_SFINAE
599 function(clear_type*) : base_type() {}
602 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
604 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
606 self_type& operator=(const self_type& f)
608 self_type(f).swap(*this);
612 template<typename Functor>
613 #ifndef BOOST_NO_SFINAE
614 typename enable_if_c<
615 (::boost::type_traits::ice_not<
616 (is_integral<Functor>::value)>::value),
623 self_type(f).swap(*this);
627 #ifndef BOOST_NO_SFINAE
628 self_type& operator=(clear_type*)
635 self_type& operator=(const base_type& f)
637 self_type(f).swap(*this);
642 #undef BOOST_FUNCTION_PARTIAL_SPEC
643 #endif // have partial specialization
645 } // end namespace boost
647 // Cleanup after ourselves...
648 #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
649 #undef BOOST_FUNCTION_COMMA
650 #undef BOOST_FUNCTION_FUNCTION
651 #undef BOOST_FUNCTION_FUNCTION_INVOKER
652 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
653 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
654 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
655 #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
656 #undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
657 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
658 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
659 #undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
660 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
661 #undef BOOST_FUNCTION_TEMPLATE_PARMS
662 #undef BOOST_FUNCTION_TEMPLATE_ARGS
663 #undef BOOST_FUNCTION_PARMS
664 #undef BOOST_FUNCTION_PARM
665 #undef BOOST_FUNCTION_ARGS
666 #undef BOOST_FUNCTION_ARG_TYPE
667 #undef BOOST_FUNCTION_ARG_TYPES