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 #ifndef BOOST_NO_VOID_RETURNS
257 typedef R result_type;
259 typedef internal_result_type result_type;
260 #endif // BOOST_NO_VOID_RETURNS
261 #ifndef BOOST_FUNCTION_NO_DEPRECATED
262 typedef Policy policy_type;
263 typedef Mixin mixin_type;
264 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
265 typedef Allocator allocator_type;
266 typedef BOOST_FUNCTION_FUNCTION self_type;
268 BOOST_FUNCTION_FUNCTION() : function_base()
269 #ifndef BOOST_FUNCTION_NO_DEPRECATED
271 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
274 #ifndef BOOST_FUNCTION_NO_DEPRECATED
275 explicit BOOST_FUNCTION_FUNCTION(const Mixin& m) :
281 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
283 // MSVC chokes if the following two constructors are collapsed into
284 // one with a default parameter.
285 template<typename Functor>
286 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) :
288 #ifndef BOOST_FUNCTION_NO_DEPRECATED
290 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
296 #ifndef BOOST_FUNCTION_NO_DEPRECATED
297 template<typename Functor>
298 BOOST_FUNCTION_FUNCTION(Functor f, const Mixin& m) :
305 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
307 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
309 #ifndef BOOST_FUNCTION_NO_DEPRECATED
310 Mixin(static_cast<const Mixin&>(f)),
311 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
314 this->assign_to_own(f);
317 ~BOOST_FUNCTION_FUNCTION() { clear(); }
319 result_type operator()(BOOST_FUNCTION_PARMS) const
321 assert(!this->empty());
323 #ifndef BOOST_FUNCTION_NO_DEPRECATED
325 policy.precall(this);
326 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
328 internal_result_type result = invoker(function_base::functor
330 BOOST_FUNCTION_ARGS);
332 #ifndef BOOST_FUNCTION_NO_DEPRECATED
333 policy.postcall(this);
334 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
336 #ifndef BOOST_NO_VOID_RETURNS
337 return static_cast<result_type>(result);
340 #endif // BOOST_NO_VOID_RETURNS
343 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
344 // when to use self_type is obnoxious. MSVC cannot handle self_type as
345 // the return type of these assignment operators, but Borland C++ cannot
346 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
348 template<typename Functor>
349 BOOST_FUNCTION_FUNCTION&
350 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
352 #ifndef BOOST_FUNCTION_NO_DEPRECATED
353 self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
355 self_type(f).swap(*this);
356 #endif // BOOST_FUNCTION_NO_DEPRECATED
360 #ifndef BOOST_FUNCTION_NO_DEPRECATED
361 template<typename Functor>
362 BOOST_FUNCTION_DEPRECATED_PRE
363 void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
365 BOOST_FUNCTION_DEPRECATED_INNER
366 self_type(f, static_cast<const Mixin&>(*this)).swap(*this);
368 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
370 // Assignment from another BOOST_FUNCTION_FUNCTION
371 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
376 self_type(f).swap(*this);
380 #ifndef BOOST_FUNCTION_NO_DEPRECATED
381 // Assignment from another BOOST_FUNCTION_FUNCTION
382 BOOST_FUNCTION_DEPRECATED_PRE
383 void set(const BOOST_FUNCTION_FUNCTION& f)
385 BOOST_FUNCTION_DEPRECATED_INNER
389 self_type(f).swap(*this);
391 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
393 void swap(BOOST_FUNCTION_FUNCTION& other)
398 std::swap(function_base::manager, other.manager);
399 std::swap(function_base::functor, other.functor);
400 std::swap(invoker, other.invoker);
401 #ifndef BOOST_FUNCTION_NO_DEPRECATED
402 std::swap(static_cast<Mixin&>(*this), static_cast<Mixin&>(other));
403 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
406 // Clear out a target, if there is one
409 if (function_base::manager) {
410 function_base::functor =
411 function_base::manager(function_base::functor,
412 detail::function::destroy_functor_tag);
415 function_base::manager = 0;
420 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
424 function_base::manager = f.manager;
425 function_base::functor =
426 f.manager(f.functor, detail::function::clone_functor_tag);
430 template<typename Functor>
431 void assign_to(Functor f)
433 typedef typename detail::function::get_function_tag<Functor>::type tag;
434 this->assign_to(f, tag());
437 template<typename FunctionPtr>
438 void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
443 typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
445 R BOOST_FUNCTION_COMMA
446 BOOST_FUNCTION_TEMPLATE_ARGS
450 invoker = &invoker_type::invoke;
451 function_base::manager =
452 &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
453 function_base::functor =
454 function_base::manager(detail::function::any_pointer(
455 // should be a reinterpret cast, but some compilers
456 // insist on giving cv-qualifiers to free functions
459 detail::function::clone_functor_tag);
463 #if BOOST_FUNCTION_NUM_ARGS > 0
464 template<typename MemberPtr>
465 void assign_to(MemberPtr f, detail::function::member_ptr_tag)
467 this->assign_to(mem_fn(f));
469 #endif // BOOST_FUNCTION_NUM_ARGS > 0
471 template<typename FunctionObj>
472 void assign_to(FunctionObj f, detail::function::function_obj_tag)
474 if (!detail::function::has_empty_target(addressof(f))) {
476 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
478 R BOOST_FUNCTION_COMMA
479 BOOST_FUNCTION_TEMPLATE_ARGS
483 invoker = &invoker_type::invoke;
484 function_base::manager = &detail::function::functor_manager<
485 FunctionObj, Allocator>::manage;
486 #ifndef BOOST_NO_STD_ALLOCATOR
487 typedef typename Allocator::template rebind<FunctionObj>::other
489 typedef typename allocator_type::pointer pointer_type;
490 allocator_type allocator;
491 pointer_type copy = allocator.allocate(1);
492 allocator.construct(copy, f);
494 // Get back to the original pointer type
495 FunctionObj* new_f = static_cast<FunctionObj*>(copy);
497 FunctionObj* new_f = new FunctionObj(f);
498 #endif // BOOST_NO_STD_ALLOCATOR
499 function_base::functor =
500 detail::function::any_pointer(static_cast<void*>(new_f));
504 template<typename FunctionObj>
505 void assign_to(const reference_wrapper<FunctionObj>& f,
506 detail::function::function_obj_ref_tag)
508 if (!detail::function::has_empty_target(f.get_pointer())) {
510 typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
512 R BOOST_FUNCTION_COMMA
513 BOOST_FUNCTION_TEMPLATE_ARGS
517 invoker = &invoker_type::invoke;
518 function_base::manager = &detail::function::trivial_manager;
519 function_base::functor =
520 function_base::manager(
521 detail::function::any_pointer(
522 const_cast<FunctionObj*>(f.get_pointer())),
523 detail::function::clone_functor_tag);
527 template<typename FunctionObj>
528 void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
531 typename detail::function::
532 BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
534 R BOOST_FUNCTION_COMMA
535 BOOST_FUNCTION_TEMPLATE_ARGS
538 invoker = &invoker_type::invoke;
539 function_base::manager = &detail::function::trivial_manager;
540 function_base::functor = detail::function::any_pointer(this);
543 typedef internal_result_type (*invoker_type)(detail::function::any_pointer
545 BOOST_FUNCTION_TEMPLATE_ARGS);
547 invoker_type invoker;
550 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
551 #ifndef BOOST_FUNCTION_NO_DEPRECATED
552 typename Policy, typename Mixin,
553 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
555 inline void swap(BOOST_FUNCTION_FUNCTION<
556 R BOOST_FUNCTION_COMMA
557 BOOST_FUNCTION_TEMPLATE_ARGS ,
558 #ifndef BOOST_FUNCTION_NO_DEPRECATED
561 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
564 BOOST_FUNCTION_FUNCTION<
565 R BOOST_FUNCTION_COMMA
566 BOOST_FUNCTION_TEMPLATE_ARGS,
567 #ifndef BOOST_FUNCTION_NO_DEPRECATED
570 #endif // ndef BOOST_FUNCTION_NO_DEPRECATED
578 // Cleanup after ourselves...
579 #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
580 #undef BOOST_FUNCTION_COMMA
581 #undef BOOST_FUNCTION_FUNCTION
582 #undef BOOST_FUNCTION_FUNCTION_INVOKER
583 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
584 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
585 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
586 #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
587 #undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
588 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
589 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
590 #undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
591 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER