1 // Boost.Function library
3 // Copyright (C) 2001 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
19 #ifndef BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP
20 #define BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP
23 # include <boost/config.hpp>
24 # include <boost/function/function_base.hpp>
25 # include <boost/mem_fn.hpp>
26 #endif // BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP
28 // Type of the default allocator
29 #ifndef BOOST_NO_STD_ALLOCATOR
30 # define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
32 # define BOOST_FUNCTION_DEFAULT_ALLOCATOR int
33 #endif // BOOST_NO_STD_ALLOCATOR
35 // Comma if nonzero number of arguments
36 #if BOOST_FUNCTION_NUM_ARGS == 0
37 # define BOOST_FUNCTION_COMMA
39 # define BOOST_FUNCTION_COMMA ,
40 #endif // BOOST_FUNCTION_NUM_ARGS > 0
42 // Class names used in this version of the code
43 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
44 #define BOOST_FUNCTION_FUNCTION_INVOKER \
45 BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
46 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
47 BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
48 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
49 BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
50 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
51 BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
52 #define BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER \
53 BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
54 #define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \
55 BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
56 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
57 BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
58 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
59 BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
60 #define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \
61 BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
68 typename R BOOST_FUNCTION_COMMA
69 BOOST_FUNCTION_TEMPLATE_PARMS
71 struct BOOST_FUNCTION_FUNCTION_INVOKER
73 static R invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
76 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
77 return f(BOOST_FUNCTION_ARGS);
83 typename R BOOST_FUNCTION_COMMA
84 BOOST_FUNCTION_TEMPLATE_PARMS
86 struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
88 static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
92 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
93 f(BOOST_FUNCTION_ARGS);
100 typename R BOOST_FUNCTION_COMMA
101 BOOST_FUNCTION_TEMPLATE_PARMS
103 struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
105 static R invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
106 BOOST_FUNCTION_PARMS)
109 FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
110 return (*f)(BOOST_FUNCTION_ARGS);
115 typename FunctionObj,
116 typename R BOOST_FUNCTION_COMMA
117 BOOST_FUNCTION_TEMPLATE_PARMS
119 struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
121 static unusable invoke(any_pointer function_obj_ptr
123 BOOST_FUNCTION_PARMS)
126 FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
127 (*f)(BOOST_FUNCTION_ARGS);
133 typename FunctionObj,
134 typename R BOOST_FUNCTION_COMMA
135 BOOST_FUNCTION_TEMPLATE_PARMS
137 struct BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
139 static R invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
141 FunctionObj f = FunctionObj();
142 return f(BOOST_FUNCTION_ARGS);
147 typename FunctionObj,
148 typename R BOOST_FUNCTION_COMMA
149 BOOST_FUNCTION_TEMPLATE_PARMS
151 struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
153 static unusable invoke(any_pointer BOOST_FUNCTION_COMMA
154 BOOST_FUNCTION_PARMS)
157 FunctionObj f = FunctionObj();
158 f(BOOST_FUNCTION_ARGS);
164 typename FunctionPtr,
165 typename R BOOST_FUNCTION_COMMA
166 BOOST_FUNCTION_TEMPLATE_PARMS
168 struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
170 typedef typename ct_if<(is_void<R>::value),
171 BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
173 R BOOST_FUNCTION_COMMA
174 BOOST_FUNCTION_TEMPLATE_ARGS
176 BOOST_FUNCTION_FUNCTION_INVOKER<
178 R BOOST_FUNCTION_COMMA
179 BOOST_FUNCTION_TEMPLATE_ARGS
185 typename FunctionObj,
186 typename R BOOST_FUNCTION_COMMA
187 BOOST_FUNCTION_TEMPLATE_PARMS
189 struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
191 typedef typename ct_if<(is_void<R>::value),
192 BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
194 R BOOST_FUNCTION_COMMA
195 BOOST_FUNCTION_TEMPLATE_ARGS
197 BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
199 R BOOST_FUNCTION_COMMA
200 BOOST_FUNCTION_TEMPLATE_ARGS
206 typename FunctionObj,
207 typename R BOOST_FUNCTION_COMMA
208 BOOST_FUNCTION_TEMPLATE_PARMS
210 struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
212 typedef typename ct_if<(is_void<R>::value),
213 BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER<
215 R BOOST_FUNCTION_COMMA
216 BOOST_FUNCTION_TEMPLATE_ARGS
218 BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER<
220 R BOOST_FUNCTION_COMMA
221 BOOST_FUNCTION_TEMPLATE_ARGS
226 } // end namespace function
227 } // end namespace detail
230 typename R BOOST_FUNCTION_COMMA
231 BOOST_FUNCTION_TEMPLATE_PARMS,
232 #ifndef BOOST_FUNCTION_NO_DEPRECATED
233 typename Policy = empty_function_policy,
234 typename Mixin = empty_function_mixin,
235 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
236 typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
238 class BOOST_FUNCTION_FUNCTION : public function_base
239 #ifndef BOOST_FUNCTION_NO_DEPRECATED
241 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
243 typedef typename detail::function::function_return_type<R>::type
244 internal_result_type;
247 BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
249 #if BOOST_FUNCTION_NUM_ARGS == 1
250 typedef T0 argument_type;
251 #elif BOOST_FUNCTION_NUM_ARGS == 2
252 typedef T0 first_argument_type;
253 typedef T1 second_argument_type;
256 BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
257 BOOST_FUNCTION_ARG_TYPES
259 #ifndef BOOST_NO_VOID_RETURNS
260 typedef R result_type;
262 typedef internal_result_type result_type;
263 #endif // BOOST_NO_VOID_RETURNS
264 #ifndef BOOST_FUNCTION_NO_DEPRECATED
265 typedef Policy policy_type;
266 typedef Mixin mixin_type;
267 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
268 typedef Allocator allocator_type;
269 typedef BOOST_FUNCTION_FUNCTION self_type;
271 BOOST_FUNCTION_FUNCTION() : function_base()
272 #ifndef BOOST_FUNCTION_NO_DEPRECATED
274 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
277 #ifndef BOOST_FUNCTION_NO_DEPRECATED
278 explicit BOOST_FUNCTION_FUNCTION(const Mixin& m) :
284 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
286 // MSVC chokes if the following two constructors are collapsed into
287 // one with a default parameter.
288 template<typename Functor>
289 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) :
291 #ifndef BOOST_FUNCTION_NO_DEPRECATED
293 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
299 #ifndef BOOST_FUNCTION_NO_DEPRECATED
300 template<typename Functor>
301 BOOST_FUNCTION_FUNCTION(Functor f, const Mixin& m) :
308 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
310 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
312 #ifndef BOOST_FUNCTION_NO_DEPRECATED
313 Mixin(static_cast<const Mixin&>(f)),
314 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
317 this->assign_to_own(f);
320 ~BOOST_FUNCTION_FUNCTION() { clear(); }
322 result_type operator()(BOOST_FUNCTION_PARMS) const
324 assert(!this->empty());
326 #ifndef BOOST_FUNCTION_NO_DEPRECATED
328 policy.precall(this);
329 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
331 internal_result_type result = invoker(function_base::functor
333 BOOST_FUNCTION_ARGS);
335 #ifndef BOOST_FUNCTION_NO_DEPRECATED
336 policy.postcall(this);
337 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
339 #ifndef BOOST_NO_VOID_RETURNS
340 return static_cast<result_type>(result);
343 #endif // BOOST_NO_VOID_RETURNS
346 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
347 // when to use self_type is obnoxious. MSVC cannot handle self_type as
348 // the return type of these assignment operators, but Borland C++ cannot
349 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
351 template<typename Functor>
352 BOOST_FUNCTION_FUNCTION&
353 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
355 #ifndef BOOST_FUNCTION_NO_DEPRECATED
356 self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
358 self_type(f).swap(*this);
359 #endif // BOOST_FUNCTION_NO_DEPRECATED
363 #ifndef BOOST_FUNCTION_NO_DEPRECATED
364 template<typename Functor>
365 BOOST_FUNCTION_DEPRECATED_PRE
366 void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
368 BOOST_FUNCTION_DEPRECATED_INNER
369 self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
371 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
373 // Assignment from another BOOST_FUNCTION_FUNCTION
374 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
379 self_type(f).swap(*this);
383 #ifndef BOOST_FUNCTION_NO_DEPRECATED
384 // Assignment from another BOOST_FUNCTION_FUNCTION
385 BOOST_FUNCTION_DEPRECATED_PRE
386 void set(const BOOST_FUNCTION_FUNCTION& f)
388 BOOST_FUNCTION_DEPRECATED_INNER
392 self_type(f).swap(*this);
394 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
396 void swap(BOOST_FUNCTION_FUNCTION& other)
401 std::swap(function_base::manager, other.manager);
402 std::swap(function_base::functor, other.functor);
403 std::swap(invoker, other.invoker);
404 #ifndef BOOST_FUNCTION_NO_DEPRECATED
405 std::swap(static_cast<Mixin&>(*this), static_cast<Mixin&>(other));
406 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
409 // Clear out a target, if there is one
412 if (function_base::manager) {
413 function_base::functor =
414 function_base::manager(function_base::functor,
415 detail::function::destroy_functor_tag);
418 function_base::manager = 0;
422 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
423 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
424 operator bool () const { return !this->empty(); }
431 typedef void (dummy::*safe_bool)();
434 operator safe_bool () const
435 { return (this->empty())? 0 : &dummy::nonnull; }
437 bool operator!() const
438 { return this->empty(); }
442 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
446 function_base::manager = f.manager;
447 function_base::functor =
448 f.manager(f.functor, detail::function::clone_functor_tag);
452 template<typename Functor>
453 void assign_to(Functor f)
455 typedef typename detail::function::get_function_tag<Functor>::type tag;
456 this->assign_to(f, tag());
459 template<typename FunctionPtr>
460 void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
465 typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
467 R BOOST_FUNCTION_COMMA
468 BOOST_FUNCTION_TEMPLATE_ARGS
472 invoker = &invoker_type::invoke;
473 function_base::manager =
474 &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
475 function_base::functor =
476 function_base::manager(detail::function::any_pointer(
477 // should be a reinterpret cast, but some compilers
478 // insist on giving cv-qualifiers to free functions
481 detail::function::clone_functor_tag);
485 #if BOOST_FUNCTION_NUM_ARGS > 0
486 template<typename MemberPtr>
487 void assign_to(MemberPtr f, detail::function::member_ptr_tag)
489 this->assign_to(mem_fn(f));
491 #endif // BOOST_FUNCTION_NUM_ARGS > 0
493 template<typename FunctionObj>
494 void assign_to(FunctionObj f, detail::function::function_obj_tag)
496 if (!detail::function::has_empty_target(addressof(f))) {
498 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
500 R BOOST_FUNCTION_COMMA
501 BOOST_FUNCTION_TEMPLATE_ARGS
505 invoker = &invoker_type::invoke;
506 function_base::manager = &detail::function::functor_manager<
507 FunctionObj, Allocator>::manage;
508 #ifndef BOOST_NO_STD_ALLOCATOR
509 typedef typename Allocator::template rebind<FunctionObj>::other
511 typedef typename allocator_type::pointer pointer_type;
512 allocator_type allocator;
513 pointer_type copy = allocator.allocate(1);
514 allocator.construct(copy, f);
516 // Get back to the original pointer type
517 FunctionObj* new_f = static_cast<FunctionObj*>(copy);
519 FunctionObj* new_f = new FunctionObj(f);
520 #endif // BOOST_NO_STD_ALLOCATOR
521 function_base::functor =
522 detail::function::any_pointer(static_cast<void*>(new_f));
526 template<typename FunctionObj>
527 void assign_to(const reference_wrapper<FunctionObj>& f,
528 detail::function::function_obj_ref_tag)
530 if (!detail::function::has_empty_target(f.get_pointer())) {
532 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
534 R BOOST_FUNCTION_COMMA
535 BOOST_FUNCTION_TEMPLATE_ARGS
539 invoker = &invoker_type::invoke;
540 function_base::manager = &detail::function::trivial_manager;
541 function_base::functor =
542 function_base::manager(
543 detail::function::any_pointer(
544 const_cast<FunctionObj*>(f.get_pointer())),
545 detail::function::clone_functor_tag);
549 template<typename FunctionObj>
550 void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
553 typename detail::function::
554 BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
556 R BOOST_FUNCTION_COMMA
557 BOOST_FUNCTION_TEMPLATE_ARGS
560 invoker = &invoker_type::invoke;
561 function_base::manager = &detail::function::trivial_manager;
562 function_base::functor = detail::function::any_pointer(this);
565 typedef internal_result_type (*invoker_type)(detail::function::any_pointer
567 BOOST_FUNCTION_TEMPLATE_ARGS);
569 invoker_type invoker;
572 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
573 #ifndef BOOST_FUNCTION_NO_DEPRECATED
574 typename Policy, typename Mixin,
575 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
577 inline void swap(BOOST_FUNCTION_FUNCTION<
578 R BOOST_FUNCTION_COMMA
579 BOOST_FUNCTION_TEMPLATE_ARGS ,
580 #ifndef BOOST_FUNCTION_NO_DEPRECATED
583 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
586 BOOST_FUNCTION_FUNCTION<
587 R BOOST_FUNCTION_COMMA
588 BOOST_FUNCTION_TEMPLATE_ARGS,
589 #ifndef BOOST_FUNCTION_NO_DEPRECATED
592 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
600 // Cleanup after ourselves...
601 #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
602 #undef BOOST_FUNCTION_COMMA
603 #undef BOOST_FUNCTION_FUNCTION
604 #undef BOOST_FUNCTION_FUNCTION_INVOKER
605 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
606 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
607 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
608 #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
609 #undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
610 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
611 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
612 #undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
613 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER