1 // Boost.Function library
3 // Copyright (C) 2001-2003 Doug Gregor (gregod@cs.rpi.edu)
5 // Permission to copy, use, sell and distribute this software is granted
6 // provided this copyright notice appears in all copies.
7 // Permission to modify the code and to distribute modified code is granted
8 // provided this copyright notice appears in all copies, and a notice
9 // that the code was modified is included with the copyright notice.
11 // This software is provided "as is" without express or implied warranty,
12 // and with no claim as to its suitability for any purpose.
14 // For more information, see http://www.boost.org
16 // Note: this header is a header template and must NOT have multiple-inclusion
18 #include <boost/function/detail/prologue.hpp>
20 #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
22 #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
24 #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
26 #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
28 #define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
30 #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
31 typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(arg, BOOST_PP_CAT(BOOST_PP_INC(I),_type));
33 #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
35 // Type of the default allocator
36 #ifndef BOOST_NO_STD_ALLOCATOR
37 # define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
39 # define BOOST_FUNCTION_DEFAULT_ALLOCATOR int
40 #endif // BOOST_NO_STD_ALLOCATOR
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_STATELESS_FUNCTION_OBJ_INVOKER \
60 BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
61 #define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \
62 BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
63 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
64 BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
65 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
66 BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
67 #define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \
68 BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
75 typename R BOOST_FUNCTION_COMMA
76 BOOST_FUNCTION_TEMPLATE_PARMS
78 struct BOOST_FUNCTION_FUNCTION_INVOKER
80 static R invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
83 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
84 return f(BOOST_FUNCTION_ARGS);
90 typename R BOOST_FUNCTION_COMMA
91 BOOST_FUNCTION_TEMPLATE_PARMS
93 struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
95 static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
99 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
100 f(BOOST_FUNCTION_ARGS);
106 typename FunctionObj,
107 typename R BOOST_FUNCTION_COMMA
108 BOOST_FUNCTION_TEMPLATE_PARMS
110 struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
112 static R invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
113 BOOST_FUNCTION_PARMS)
116 FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
117 return (*f)(BOOST_FUNCTION_ARGS);
122 typename FunctionObj,
123 typename R BOOST_FUNCTION_COMMA
124 BOOST_FUNCTION_TEMPLATE_PARMS
126 struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
128 static unusable invoke(any_pointer function_obj_ptr
130 BOOST_FUNCTION_PARMS)
133 FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
134 (*f)(BOOST_FUNCTION_ARGS);
140 typename FunctionObj,
141 typename R BOOST_FUNCTION_COMMA
142 BOOST_FUNCTION_TEMPLATE_PARMS
144 struct BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
146 static R invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
148 FunctionObj f = FunctionObj();
149 return f(BOOST_FUNCTION_ARGS);
154 typename FunctionObj,
155 typename R BOOST_FUNCTION_COMMA
156 BOOST_FUNCTION_TEMPLATE_PARMS
158 struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
160 static unusable invoke(any_pointer BOOST_FUNCTION_COMMA
161 BOOST_FUNCTION_PARMS)
164 FunctionObj f = FunctionObj();
165 f(BOOST_FUNCTION_ARGS);
171 typename FunctionPtr,
172 typename R BOOST_FUNCTION_COMMA
173 BOOST_FUNCTION_TEMPLATE_PARMS
175 struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
177 typedef typename ct_if<(is_void<R>::value),
178 BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
180 R BOOST_FUNCTION_COMMA
181 BOOST_FUNCTION_TEMPLATE_ARGS
183 BOOST_FUNCTION_FUNCTION_INVOKER<
185 R BOOST_FUNCTION_COMMA
186 BOOST_FUNCTION_TEMPLATE_ARGS
192 typename FunctionObj,
193 typename R BOOST_FUNCTION_COMMA
194 BOOST_FUNCTION_TEMPLATE_PARMS
196 struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
198 typedef typename ct_if<(is_void<R>::value),
199 BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
201 R BOOST_FUNCTION_COMMA
202 BOOST_FUNCTION_TEMPLATE_ARGS
204 BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
206 R BOOST_FUNCTION_COMMA
207 BOOST_FUNCTION_TEMPLATE_ARGS
213 typename FunctionObj,
214 typename R BOOST_FUNCTION_COMMA
215 BOOST_FUNCTION_TEMPLATE_PARMS
217 struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
219 typedef typename ct_if<(is_void<R>::value),
220 BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER<
222 R BOOST_FUNCTION_COMMA
223 BOOST_FUNCTION_TEMPLATE_ARGS
225 BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER<
227 R BOOST_FUNCTION_COMMA
228 BOOST_FUNCTION_TEMPLATE_ARGS
233 } // end namespace function
234 } // end namespace detail
237 typename R BOOST_FUNCTION_COMMA
238 BOOST_FUNCTION_TEMPLATE_PARMS,
239 typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
241 class BOOST_FUNCTION_FUNCTION : public function_base
243 typedef typename detail::function::function_return_type<R>::type
244 internal_result_type;
246 struct clear_type {};
249 BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
251 // add signature for boost::lambda
252 template<typename Args>
255 typedef internal_result_type type;
258 #if BOOST_FUNCTION_NUM_ARGS == 1
259 typedef T0 argument_type;
260 #elif BOOST_FUNCTION_NUM_ARGS == 2
261 typedef T0 first_argument_type;
262 typedef T1 second_argument_type;
265 BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
266 BOOST_FUNCTION_ARG_TYPES
268 #ifndef BOOST_NO_VOID_RETURNS
269 typedef R result_type;
271 typedef internal_result_type result_type;
272 #endif // BOOST_NO_VOID_RETURNS
273 typedef Allocator allocator_type;
274 typedef BOOST_FUNCTION_FUNCTION self_type;
276 BOOST_FUNCTION_FUNCTION() : function_base()
279 // MSVC chokes if the following two constructors are collapsed into
280 // one with a default parameter.
281 template<typename Functor>
282 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
283 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
284 ,typename detail::function::enable_if<
285 (::boost::type_traits::ice_not<
286 (is_same<Functor, int>::value)>::value),
288 #endif // BOOST_FUNCTION_NO_ENABLE_IF
296 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
297 BOOST_FUNCTION_FUNCTION(clear_type*) : function_base(), invoker(0) {}
299 BOOST_FUNCTION_FUNCTION(int zero) : function_base(), invoker(0)
301 BOOST_ASSERT(zero == 0);
305 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
309 this->assign_to_own(f);
312 ~BOOST_FUNCTION_FUNCTION() { clear(); }
314 result_type operator()(BOOST_FUNCTION_PARMS) const
317 boost::throw_exception(bad_function_call());
319 internal_result_type result = invoker(function_base::functor
321 BOOST_FUNCTION_ARGS);
323 #ifndef BOOST_NO_VOID_RETURNS
324 return static_cast<result_type>(result);
327 #endif // BOOST_NO_VOID_RETURNS
330 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
331 // when to use self_type is obnoxious. MSVC cannot handle self_type as
332 // the return type of these assignment operators, but Borland C++ cannot
333 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
335 template<typename Functor>
336 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
337 typename detail::function::enable_if<
338 (::boost::type_traits::ice_not<
339 (is_same<Functor, int>::value)>::value),
340 BOOST_FUNCTION_FUNCTION&>::type
342 BOOST_FUNCTION_FUNCTION&
344 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
346 self_type(f).swap(*this);
350 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
351 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
357 BOOST_FUNCTION_FUNCTION& operator=(int zero)
359 BOOST_ASSERT(zero == 0);
365 // Assignment from another BOOST_FUNCTION_FUNCTION
366 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
371 self_type(f).swap(*this);
375 void swap(BOOST_FUNCTION_FUNCTION& other)
380 std::swap(function_base::manager, other.manager);
381 std::swap(function_base::functor, other.functor);
382 std::swap(invoker, other.invoker);
385 // Clear out a target, if there is one
388 if (function_base::manager) {
389 function_base::functor =
390 function_base::manager(function_base::functor,
391 detail::function::destroy_functor_tag);
394 function_base::manager = 0;
398 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
399 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
400 operator bool () const { return !this->empty(); }
407 typedef void (dummy::*safe_bool)();
410 operator safe_bool () const
411 { return (this->empty())? 0 : &dummy::nonnull; }
413 bool operator!() const
414 { return this->empty(); }
418 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
422 function_base::manager = f.manager;
423 function_base::functor =
424 f.manager(f.functor, detail::function::clone_functor_tag);
428 template<typename Functor>
429 void assign_to(Functor f)
431 typedef typename detail::function::get_function_tag<Functor>::type tag;
432 this->assign_to(f, tag());
435 template<typename FunctionPtr>
436 void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
441 typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
443 R BOOST_FUNCTION_COMMA
444 BOOST_FUNCTION_TEMPLATE_ARGS
448 invoker = &invoker_type::invoke;
449 function_base::manager =
450 &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
451 function_base::functor =
452 function_base::manager(detail::function::make_any_pointer(
453 // should be a reinterpret cast, but some compilers
454 // insist on giving cv-qualifiers to free functions
457 detail::function::clone_functor_tag);
461 #if BOOST_FUNCTION_NUM_ARGS > 0
462 template<typename MemberPtr>
463 void assign_to(MemberPtr f, detail::function::member_ptr_tag)
465 this->assign_to(mem_fn(f));
467 #endif // BOOST_FUNCTION_NUM_ARGS > 0
469 template<typename FunctionObj>
470 void assign_to(FunctionObj f, detail::function::function_obj_tag)
472 if (!detail::function::has_empty_target(addressof(f))) {
474 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
476 R BOOST_FUNCTION_COMMA
477 BOOST_FUNCTION_TEMPLATE_ARGS
481 invoker = &invoker_type::invoke;
482 function_base::manager = &detail::function::functor_manager<
483 FunctionObj, Allocator>::manage;
484 #ifndef BOOST_NO_STD_ALLOCATOR
485 typedef typename Allocator::template rebind<FunctionObj>::other
487 typedef typename allocator_type::pointer pointer_type;
488 allocator_type allocator;
489 pointer_type copy = allocator.allocate(1);
490 allocator.construct(copy, f);
492 // Get back to the original pointer type
493 FunctionObj* new_f = static_cast<FunctionObj*>(copy);
495 FunctionObj* new_f = new FunctionObj(f);
496 #endif // BOOST_NO_STD_ALLOCATOR
497 function_base::functor =
498 detail::function::make_any_pointer(static_cast<void*>(new_f));
502 template<typename FunctionObj>
503 void assign_to(const reference_wrapper<FunctionObj>& f,
504 detail::function::function_obj_ref_tag)
506 if (!detail::function::has_empty_target(f.get_pointer())) {
508 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
510 R BOOST_FUNCTION_COMMA
511 BOOST_FUNCTION_TEMPLATE_ARGS
515 invoker = &invoker_type::invoke;
516 function_base::manager = &detail::function::trivial_manager;
517 function_base::functor =
518 function_base::manager(
519 detail::function::make_any_pointer(
520 const_cast<FunctionObj*>(f.get_pointer())),
521 detail::function::clone_functor_tag);
525 template<typename FunctionObj>
526 void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
529 typename detail::function::
530 BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
532 R BOOST_FUNCTION_COMMA
533 BOOST_FUNCTION_TEMPLATE_ARGS
536 invoker = &invoker_type::invoke;
537 function_base::manager = &detail::function::trivial_manager;
538 function_base::functor = detail::function::make_any_pointer(this);
541 typedef internal_result_type (*invoker_type)(detail::function::any_pointer
543 BOOST_FUNCTION_TEMPLATE_ARGS);
545 invoker_type invoker;
548 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
550 inline void swap(BOOST_FUNCTION_FUNCTION<
551 R BOOST_FUNCTION_COMMA
552 BOOST_FUNCTION_TEMPLATE_ARGS ,
555 BOOST_FUNCTION_FUNCTION<
556 R BOOST_FUNCTION_COMMA
557 BOOST_FUNCTION_TEMPLATE_ARGS,
564 #if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
565 && !defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
566 && (BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
568 #if BOOST_FUNCTION_NUM_ARGS == 0
569 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
571 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
574 template<typename R BOOST_FUNCTION_COMMA
575 BOOST_FUNCTION_TEMPLATE_PARMS,
577 class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
578 : public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
579 BOOST_FUNCTION_COMMA Allocator>
581 typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
582 BOOST_FUNCTION_COMMA Allocator> base_type;
583 typedef function self_type;
585 struct clear_type {};
588 typedef typename base_type::allocator_type allocator_type;
590 function() : base_type() {}
592 template<typename Functor>
594 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
595 ,typename detail::function::enable_if<
596 (::boost::type_traits::ice_not<
597 (is_same<Functor, int>::value)>::value),
605 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
606 function(clear_type*) : base_type() {}
609 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
611 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
613 self_type& operator=(const self_type& f)
615 self_type(f).swap(*this);
619 template<typename Functor>
620 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
621 typename detail::function::enable_if<
622 (::boost::type_traits::ice_not<
623 (is_same<Functor, int>::value)>::value),
630 self_type(f).swap(*this);
634 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
635 self_type& operator=(clear_type*)
642 self_type& operator=(const base_type& f)
644 self_type(f).swap(*this);
649 #undef BOOST_FUNCTION_PARTIAL_SPEC
650 #endif // have partial specialization
652 } // end namespace boost
654 // Cleanup after ourselves...
655 #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
656 #undef BOOST_FUNCTION_COMMA
657 #undef BOOST_FUNCTION_FUNCTION
658 #undef BOOST_FUNCTION_FUNCTION_INVOKER
659 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
660 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
661 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
662 #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
663 #undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
664 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
665 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
666 #undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
667 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
668 #undef BOOST_FUNCTION_TEMPLATE_PARMS
669 #undef BOOST_FUNCTION_TEMPLATE_ARGS
670 #undef BOOST_FUNCTION_PARMS
671 #undef BOOST_FUNCTION_PARM
672 #undef BOOST_FUNCTION_ARGS
673 #undef BOOST_FUNCTION_ARG_TYPE
674 #undef BOOST_FUNCTION_ARG_TYPES