blob: 6256b7344867405a7c8f9150b6f81a24f63fa248 [file] [log] [blame]
Jeff Thompsona28eed82013-08-22 16:21:10 -07001// Boost.Function library
2
3// Copyright Douglas Gregor 2001-2006
4// Copyright Emil Dotchevski 2007
5// Use, modification and distribution is subject to the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9// For more information, see http://www.boost.org
10
11// Note: this header is a header template and must NOT have multiple-inclusion
12// protection.
13#include <ndnboost/function/detail/prologue.hpp>
14#include <ndnboost/detail/no_exceptions_support.hpp>
15
16#if defined(BOOST_MSVC)
17# pragma warning( push )
18# pragma warning( disable : 4127 ) // "conditional expression is constant"
19#endif
20
21#define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
22
23#define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
24
25#define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
26
27#define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
28
29#define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
30
31#define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
32 typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
33
34#define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
35
36// Comma if nonzero number of arguments
37#if BOOST_FUNCTION_NUM_ARGS == 0
38# define BOOST_FUNCTION_COMMA
39#else
40# define BOOST_FUNCTION_COMMA ,
41#endif // BOOST_FUNCTION_NUM_ARGS > 0
42
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_FUNCTION_REF_INVOKER \
54 BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
55#define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
56 BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
57#define BOOST_FUNCTION_MEMBER_INVOKER \
58 BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
59#define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
60 BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
61#define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
62 BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
63#define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
64 BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
65#define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
66 BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
67#define BOOST_FUNCTION_GET_MEMBER_INVOKER \
68 BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
69#define BOOST_FUNCTION_GET_INVOKER \
70 BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
71#define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
72
73#ifndef BOOST_NO_VOID_RETURNS
74# define BOOST_FUNCTION_VOID_RETURN_TYPE void
75# define BOOST_FUNCTION_RETURN(X) X
76#else
77# define BOOST_FUNCTION_VOID_RETURN_TYPE ndnboost::detail::function::unusable
78# define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
79#endif
80
81namespace ndnboost {
82 namespace detail {
83 namespace function {
84 template<
85 typename FunctionPtr,
86 typename R BOOST_FUNCTION_COMMA
87 BOOST_FUNCTION_TEMPLATE_PARMS
88 >
89 struct BOOST_FUNCTION_FUNCTION_INVOKER
90 {
91 static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
92 BOOST_FUNCTION_PARMS)
93 {
94 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
95 return f(BOOST_FUNCTION_ARGS);
96 }
97 };
98
99 template<
100 typename FunctionPtr,
101 typename R BOOST_FUNCTION_COMMA
102 BOOST_FUNCTION_TEMPLATE_PARMS
103 >
104 struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
105 {
106 static BOOST_FUNCTION_VOID_RETURN_TYPE
107 invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
108 BOOST_FUNCTION_PARMS)
109
110 {
111 FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
112 BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
113 }
114 };
115
116 template<
117 typename FunctionObj,
118 typename R BOOST_FUNCTION_COMMA
119 BOOST_FUNCTION_TEMPLATE_PARMS
120 >
121 struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
122 {
123 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
124 BOOST_FUNCTION_PARMS)
125
126 {
127 FunctionObj* f;
128 if (function_allows_small_object_optimization<FunctionObj>::value)
129 f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
130 else
131 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
132 return (*f)(BOOST_FUNCTION_ARGS);
133 }
134 };
135
136 template<
137 typename FunctionObj,
138 typename R BOOST_FUNCTION_COMMA
139 BOOST_FUNCTION_TEMPLATE_PARMS
140 >
141 struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
142 {
143 static BOOST_FUNCTION_VOID_RETURN_TYPE
144 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
145 BOOST_FUNCTION_PARMS)
146
147 {
148 FunctionObj* f;
149 if (function_allows_small_object_optimization<FunctionObj>::value)
150 f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
151 else
152 f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
153 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
154 }
155 };
156
157 template<
158 typename FunctionObj,
159 typename R BOOST_FUNCTION_COMMA
160 BOOST_FUNCTION_TEMPLATE_PARMS
161 >
162 struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
163 {
164 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
165 BOOST_FUNCTION_PARMS)
166
167 {
168 FunctionObj* f =
169 reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
170 return (*f)(BOOST_FUNCTION_ARGS);
171 }
172 };
173
174 template<
175 typename FunctionObj,
176 typename R BOOST_FUNCTION_COMMA
177 BOOST_FUNCTION_TEMPLATE_PARMS
178 >
179 struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
180 {
181 static BOOST_FUNCTION_VOID_RETURN_TYPE
182 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
183 BOOST_FUNCTION_PARMS)
184
185 {
186 FunctionObj* f =
187 reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
188 BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
189 }
190 };
191
192#if BOOST_FUNCTION_NUM_ARGS > 0
193 /* Handle invocation of member pointers. */
194 template<
195 typename MemberPtr,
196 typename R BOOST_FUNCTION_COMMA
197 BOOST_FUNCTION_TEMPLATE_PARMS
198 >
199 struct BOOST_FUNCTION_MEMBER_INVOKER
200 {
201 static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
202 BOOST_FUNCTION_PARMS)
203
204 {
205 MemberPtr* f =
206 reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
207 return ndnboost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
208 }
209 };
210
211 template<
212 typename MemberPtr,
213 typename R BOOST_FUNCTION_COMMA
214 BOOST_FUNCTION_TEMPLATE_PARMS
215 >
216 struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
217 {
218 static BOOST_FUNCTION_VOID_RETURN_TYPE
219 invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
220 BOOST_FUNCTION_PARMS)
221
222 {
223 MemberPtr* f =
224 reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
225 BOOST_FUNCTION_RETURN(ndnboost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
226 }
227 };
228#endif
229
230 template<
231 typename FunctionPtr,
232 typename R BOOST_FUNCTION_COMMA
233 BOOST_FUNCTION_TEMPLATE_PARMS
234 >
235 struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
236 {
237 typedef typename mpl::if_c<(is_void<R>::value),
238 BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
239 FunctionPtr,
240 R BOOST_FUNCTION_COMMA
241 BOOST_FUNCTION_TEMPLATE_ARGS
242 >,
243 BOOST_FUNCTION_FUNCTION_INVOKER<
244 FunctionPtr,
245 R BOOST_FUNCTION_COMMA
246 BOOST_FUNCTION_TEMPLATE_ARGS
247 >
248 >::type type;
249 };
250
251 template<
252 typename FunctionObj,
253 typename R BOOST_FUNCTION_COMMA
254 BOOST_FUNCTION_TEMPLATE_PARMS
255 >
256 struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
257 {
258 typedef typename mpl::if_c<(is_void<R>::value),
259 BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
260 FunctionObj,
261 R BOOST_FUNCTION_COMMA
262 BOOST_FUNCTION_TEMPLATE_ARGS
263 >,
264 BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
265 FunctionObj,
266 R BOOST_FUNCTION_COMMA
267 BOOST_FUNCTION_TEMPLATE_ARGS
268 >
269 >::type type;
270 };
271
272 template<
273 typename FunctionObj,
274 typename R BOOST_FUNCTION_COMMA
275 BOOST_FUNCTION_TEMPLATE_PARMS
276 >
277 struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
278 {
279 typedef typename mpl::if_c<(is_void<R>::value),
280 BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
281 FunctionObj,
282 R BOOST_FUNCTION_COMMA
283 BOOST_FUNCTION_TEMPLATE_ARGS
284 >,
285 BOOST_FUNCTION_FUNCTION_REF_INVOKER<
286 FunctionObj,
287 R BOOST_FUNCTION_COMMA
288 BOOST_FUNCTION_TEMPLATE_ARGS
289 >
290 >::type type;
291 };
292
293#if BOOST_FUNCTION_NUM_ARGS > 0
294 /* Retrieve the appropriate invoker for a member pointer. */
295 template<
296 typename MemberPtr,
297 typename R BOOST_FUNCTION_COMMA
298 BOOST_FUNCTION_TEMPLATE_PARMS
299 >
300 struct BOOST_FUNCTION_GET_MEMBER_INVOKER
301 {
302 typedef typename mpl::if_c<(is_void<R>::value),
303 BOOST_FUNCTION_VOID_MEMBER_INVOKER<
304 MemberPtr,
305 R BOOST_FUNCTION_COMMA
306 BOOST_FUNCTION_TEMPLATE_ARGS
307 >,
308 BOOST_FUNCTION_MEMBER_INVOKER<
309 MemberPtr,
310 R BOOST_FUNCTION_COMMA
311 BOOST_FUNCTION_TEMPLATE_ARGS
312 >
313 >::type type;
314 };
315#endif
316
317 /* Given the tag returned by get_function_tag, retrieve the
318 actual invoker that will be used for the given function
319 object.
320
321 Each specialization contains an "apply" nested class template
322 that accepts the function object, return type, function
323 argument types, and allocator. The resulting "apply" class
324 contains two typedefs, "invoker_type" and "manager_type",
325 which correspond to the invoker and manager types. */
326 template<typename Tag>
327 struct BOOST_FUNCTION_GET_INVOKER { };
328
329 /* Retrieve the invoker for a function pointer. */
330 template<>
331 struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
332 {
333 template<typename FunctionPtr,
334 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
335 struct apply
336 {
337 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
338 FunctionPtr,
339 R BOOST_FUNCTION_COMMA
340 BOOST_FUNCTION_TEMPLATE_ARGS
341 >::type
342 invoker_type;
343
344 typedef functor_manager<FunctionPtr> manager_type;
345 };
346
347 template<typename FunctionPtr,
348 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
349 typename Allocator>
350 struct apply_a
351 {
352 typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
353 FunctionPtr,
354 R BOOST_FUNCTION_COMMA
355 BOOST_FUNCTION_TEMPLATE_ARGS
356 >::type
357 invoker_type;
358
359 typedef functor_manager<FunctionPtr> manager_type;
360 };
361 };
362
363#if BOOST_FUNCTION_NUM_ARGS > 0
364 /* Retrieve the invoker for a member pointer. */
365 template<>
366 struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
367 {
368 template<typename MemberPtr,
369 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
370 struct apply
371 {
372 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
373 MemberPtr,
374 R BOOST_FUNCTION_COMMA
375 BOOST_FUNCTION_TEMPLATE_ARGS
376 >::type
377 invoker_type;
378
379 typedef functor_manager<MemberPtr> manager_type;
380 };
381
382 template<typename MemberPtr,
383 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
384 typename Allocator>
385 struct apply_a
386 {
387 typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
388 MemberPtr,
389 R BOOST_FUNCTION_COMMA
390 BOOST_FUNCTION_TEMPLATE_ARGS
391 >::type
392 invoker_type;
393
394 typedef functor_manager<MemberPtr> manager_type;
395 };
396 };
397#endif
398
399 /* Retrieve the invoker for a function object. */
400 template<>
401 struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
402 {
403 template<typename FunctionObj,
404 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
405 struct apply
406 {
407 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
408 FunctionObj,
409 R BOOST_FUNCTION_COMMA
410 BOOST_FUNCTION_TEMPLATE_ARGS
411 >::type
412 invoker_type;
413
414 typedef functor_manager<FunctionObj> manager_type;
415 };
416
417 template<typename FunctionObj,
418 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
419 typename Allocator>
420 struct apply_a
421 {
422 typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
423 FunctionObj,
424 R BOOST_FUNCTION_COMMA
425 BOOST_FUNCTION_TEMPLATE_ARGS
426 >::type
427 invoker_type;
428
429 typedef functor_manager_a<FunctionObj, Allocator> manager_type;
430 };
431 };
432
433 /* Retrieve the invoker for a reference to a function object. */
434 template<>
435 struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
436 {
437 template<typename RefWrapper,
438 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
439 struct apply
440 {
441 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
442 typename RefWrapper::type,
443 R BOOST_FUNCTION_COMMA
444 BOOST_FUNCTION_TEMPLATE_ARGS
445 >::type
446 invoker_type;
447
448 typedef reference_manager<typename RefWrapper::type> manager_type;
449 };
450
451 template<typename RefWrapper,
452 typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
453 typename Allocator>
454 struct apply_a
455 {
456 typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
457 typename RefWrapper::type,
458 R BOOST_FUNCTION_COMMA
459 BOOST_FUNCTION_TEMPLATE_ARGS
460 >::type
461 invoker_type;
462
463 typedef reference_manager<typename RefWrapper::type> manager_type;
464 };
465 };
466
467
468 /**
469 * vtable for a specific ndnboost::function instance. This
470 * structure must be an aggregate so that we can use static
471 * initialization in ndnboost::function's assign_to and assign_to_a
472 * members. It therefore cannot have any constructors,
473 * destructors, base classes, etc.
474 */
475 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
476 struct BOOST_FUNCTION_VTABLE
477 {
478#ifndef BOOST_NO_VOID_RETURNS
479 typedef R result_type;
480#else
481 typedef typename function_return_type<R>::type result_type;
482#endif // BOOST_NO_VOID_RETURNS
483
484 typedef result_type (*invoker_type)(function_buffer&
485 BOOST_FUNCTION_COMMA
486 BOOST_FUNCTION_TEMPLATE_ARGS);
487
488 template<typename F>
489 bool assign_to(F f, function_buffer& functor) const
490 {
491 typedef typename get_function_tag<F>::type tag;
492 return assign_to(f, functor, tag());
493 }
494 template<typename F,typename Allocator>
495 bool assign_to_a(F f, function_buffer& functor, Allocator a) const
496 {
497 typedef typename get_function_tag<F>::type tag;
498 return assign_to_a(f, functor, a, tag());
499 }
500
501 void clear(function_buffer& functor) const
502 {
503 if (base.manager)
504 base.manager(functor, functor, destroy_functor_tag);
505 }
506
507 private:
508 // Function pointers
509 template<typename FunctionPtr>
510 bool
511 assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
512 {
513 this->clear(functor);
514 if (f) {
515 // should be a reinterpret cast, but some compilers insist
516 // on giving cv-qualifiers to free functions
517 functor.func_ptr = reinterpret_cast<void (*)()>(f);
518 return true;
519 } else {
520 return false;
521 }
522 }
523 template<typename FunctionPtr,typename Allocator>
524 bool
525 assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
526 {
527 return assign_to(f,functor,function_ptr_tag());
528 }
529
530 // Member pointers
531#if BOOST_FUNCTION_NUM_ARGS > 0
532 template<typename MemberPtr>
533 bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
534 {
535 // DPG TBD: Add explicit support for member function
536 // objects, so we invoke through mem_fn() but we retain the
537 // right target_type() values.
538 if (f) {
539 this->assign_to(ndnboost::mem_fn(f), functor);
540 return true;
541 } else {
542 return false;
543 }
544 }
545 template<typename MemberPtr,typename Allocator>
546 bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const
547 {
548 // DPG TBD: Add explicit support for member function
549 // objects, so we invoke through mem_fn() but we retain the
550 // right target_type() values.
551 if (f) {
552 this->assign_to_a(ndnboost::mem_fn(f), functor, a);
553 return true;
554 } else {
555 return false;
556 }
557 }
558#endif // BOOST_FUNCTION_NUM_ARGS > 0
559
560 // Function objects
561 // Assign to a function object using the small object optimization
562 template<typename FunctionObj>
563 void
564 assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
565 {
566 new (reinterpret_cast<void*>(&functor.data)) FunctionObj(f);
567 }
568 template<typename FunctionObj,typename Allocator>
569 void
570 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const
571 {
572 assign_functor(f,functor,mpl::true_());
573 }
574
575 // Assign to a function object allocated on the heap.
576 template<typename FunctionObj>
577 void
578 assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
579 {
580 functor.obj_ptr = new FunctionObj(f);
581 }
582 template<typename FunctionObj,typename Allocator>
583 void
584 assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const
585 {
586 typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
587 typedef typename Allocator::template rebind<functor_wrapper_type>::other
588 wrapper_allocator_type;
589 typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
590 wrapper_allocator_type wrapper_allocator(a);
591 wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
592 wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
593 functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
594 functor.obj_ptr = new_f;
595 }
596
597 template<typename FunctionObj>
598 bool
599 assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
600 {
601 if (!ndnboost::detail::function::has_empty_target(ndnboost::addressof(f))) {
602 assign_functor(f, functor,
603 mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
604 return true;
605 } else {
606 return false;
607 }
608 }
609 template<typename FunctionObj,typename Allocator>
610 bool
611 assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
612 {
613 if (!ndnboost::detail::function::has_empty_target(ndnboost::addressof(f))) {
614 assign_functor_a(f, functor, a,
615 mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
616 return true;
617 } else {
618 return false;
619 }
620 }
621
622 // Reference to a function object
623 template<typename FunctionObj>
624 bool
625 assign_to(const reference_wrapper<FunctionObj>& f,
626 function_buffer& functor, function_obj_ref_tag) const
627 {
628 functor.obj_ref.obj_ptr = (void *)(f.get_pointer());
629 functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
630 functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
631 return true;
632 }
633 template<typename FunctionObj,typename Allocator>
634 bool
635 assign_to_a(const reference_wrapper<FunctionObj>& f,
636 function_buffer& functor, Allocator, function_obj_ref_tag) const
637 {
638 return assign_to(f,functor,function_obj_ref_tag());
639 }
640
641 public:
642 vtable_base base;
643 invoker_type invoker;
644 };
645 } // end namespace function
646 } // end namespace detail
647
648 template<
649 typename R BOOST_FUNCTION_COMMA
650 BOOST_FUNCTION_TEMPLATE_PARMS
651 >
652 class BOOST_FUNCTION_FUNCTION : public function_base
653
654#if BOOST_FUNCTION_NUM_ARGS == 1
655
656 , public std::unary_function<T0,R>
657
658#elif BOOST_FUNCTION_NUM_ARGS == 2
659
660 , public std::binary_function<T0,T1,R>
661
662#endif
663
664 {
665 public:
666#ifndef BOOST_NO_VOID_RETURNS
667 typedef R result_type;
668#else
669 typedef typename ndnboost::detail::function::function_return_type<R>::type
670 result_type;
671#endif // BOOST_NO_VOID_RETURNS
672
673 private:
674 typedef ndnboost::detail::function::BOOST_FUNCTION_VTABLE<
675 R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
676 vtable_type;
677
678 vtable_type* get_vtable() const {
679 return reinterpret_cast<vtable_type*>(
680 reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
681 }
682
683 struct clear_type {};
684
685 public:
686 BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
687
688 // add signature for ndnboost::lambda
689 template<typename Args>
690 struct sig
691 {
692 typedef result_type type;
693 };
694
695#if BOOST_FUNCTION_NUM_ARGS == 1
696 typedef T0 argument_type;
697#elif BOOST_FUNCTION_NUM_ARGS == 2
698 typedef T0 first_argument_type;
699 typedef T1 second_argument_type;
700#endif
701
702 BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
703 BOOST_FUNCTION_ARG_TYPES
704
705 typedef BOOST_FUNCTION_FUNCTION self_type;
706
707 BOOST_FUNCTION_FUNCTION() : function_base() { }
708
709 // MSVC chokes if the following two constructors are collapsed into
710 // one with a default parameter.
711 template<typename Functor>
712 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
713#ifndef BOOST_NO_SFINAE
714 ,typename enable_if_c<
715 (ndnboost::type_traits::ice_not<
716 (is_integral<Functor>::value)>::value),
717 int>::type = 0
718#endif // BOOST_NO_SFINAE
719 ) :
720 function_base()
721 {
722 this->assign_to(f);
723 }
724 template<typename Functor,typename Allocator>
725 BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
726#ifndef BOOST_NO_SFINAE
727 ,typename enable_if_c<
728 (ndnboost::type_traits::ice_not<
729 (is_integral<Functor>::value)>::value),
730 int>::type = 0
731#endif // BOOST_NO_SFINAE
732 ) :
733 function_base()
734 {
735 this->assign_to_a(f,a);
736 }
737
738#ifndef BOOST_NO_SFINAE
739 BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
740#else
741 BOOST_FUNCTION_FUNCTION(int zero) : function_base()
742 {
743 BOOST_ASSERT(zero == 0);
744 }
745#endif
746
747 BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
748 {
749 this->assign_to_own(f);
750 }
751
752#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
753 BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
754 {
755 this->move_assign(f);
756 }
757#endif
758
759 ~BOOST_FUNCTION_FUNCTION() { clear(); }
760
761 result_type operator()(BOOST_FUNCTION_PARMS) const
762 {
763 if (this->empty())
764 ndnboost::throw_exception(bad_function_call());
765
766 return get_vtable()->invoker
767 (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
768 }
769
770 // The distinction between when to use BOOST_FUNCTION_FUNCTION and
771 // when to use self_type is obnoxious. MSVC cannot handle self_type as
772 // the return type of these assignment operators, but Borland C++ cannot
773 // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
774 // construct.
775 template<typename Functor>
776#ifndef BOOST_NO_SFINAE
777 typename enable_if_c<
778 (ndnboost::type_traits::ice_not<
779 (is_integral<Functor>::value)>::value),
780 BOOST_FUNCTION_FUNCTION&>::type
781#else
782 BOOST_FUNCTION_FUNCTION&
783#endif
784 operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
785 {
786 this->clear();
787 BOOST_TRY {
788 this->assign_to(f);
789 } BOOST_CATCH (...) {
790 vtable = 0;
791 BOOST_RETHROW;
792 }
793 BOOST_CATCH_END
794 return *this;
795 }
796 template<typename Functor,typename Allocator>
797 void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
798 {
799 this->clear();
800 BOOST_TRY{
801 this->assign_to_a(f,a);
802 } BOOST_CATCH (...) {
803 vtable = 0;
804 BOOST_RETHROW;
805 }
806 BOOST_CATCH_END
807 }
808
809#ifndef BOOST_NO_SFINAE
810 BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
811 {
812 this->clear();
813 return *this;
814 }
815#else
816 BOOST_FUNCTION_FUNCTION& operator=(int zero)
817 {
818 BOOST_ASSERT(zero == 0);
819 this->clear();
820 return *this;
821 }
822#endif
823
824 // Assignment from another BOOST_FUNCTION_FUNCTION
825 BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
826 {
827 if (&f == this)
828 return *this;
829
830 this->clear();
831 BOOST_TRY {
832 this->assign_to_own(f);
833 } BOOST_CATCH (...) {
834 vtable = 0;
835 BOOST_RETHROW;
836 }
837 BOOST_CATCH_END
838 return *this;
839 }
840
841#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
842 // Move assignment from another BOOST_FUNCTION_FUNCTION
843 BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
844 {
845
846 if (&f == this)
847 return *this;
848
849 this->clear();
850 BOOST_TRY {
851 this->move_assign(f);
852 } BOOST_CATCH (...) {
853 vtable = 0;
854 BOOST_RETHROW;
855 }
856 BOOST_CATCH_END
857 return *this;
858 }
859#endif
860
861 void swap(BOOST_FUNCTION_FUNCTION& other)
862 {
863 if (&other == this)
864 return;
865
866 BOOST_FUNCTION_FUNCTION tmp;
867 tmp.move_assign(*this);
868 this->move_assign(other);
869 other.move_assign(tmp);
870 }
871
872 // Clear out a target, if there is one
873 void clear()
874 {
875 if (vtable) {
876 if (!this->has_trivial_copy_and_destroy())
877 get_vtable()->clear(this->functor);
878 vtable = 0;
879 }
880 }
881
882#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
883 // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
884 operator bool () const { return !this->empty(); }
885#else
886 private:
887 struct dummy {
888 void nonnull() {}
889 };
890
891 typedef void (dummy::*safe_bool)();
892
893 public:
894 operator safe_bool () const
895 { return (this->empty())? 0 : &dummy::nonnull; }
896
897 bool operator!() const
898 { return this->empty(); }
899#endif
900
901 private:
902 void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
903 {
904 if (!f.empty()) {
905 this->vtable = f.vtable;
906 if (this->has_trivial_copy_and_destroy())
907 this->functor = f.functor;
908 else
909 get_vtable()->base.manager(f.functor, this->functor,
910 ndnboost::detail::function::clone_functor_tag);
911 }
912 }
913
914 template<typename Functor>
915 void assign_to(Functor f)
916 {
917 using detail::function::vtable_base;
918
919 typedef typename detail::function::get_function_tag<Functor>::type tag;
920 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
921 typedef typename get_invoker::
922 template apply<Functor, R BOOST_FUNCTION_COMMA
923 BOOST_FUNCTION_TEMPLATE_ARGS>
924 handler_type;
925
926 typedef typename handler_type::invoker_type invoker_type;
927 typedef typename handler_type::manager_type manager_type;
928
929 // Note: it is extremely important that this initialization use
930 // static initialization. Otherwise, we will have a race
931 // condition here in multi-threaded code. See
932 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
933 static const vtable_type stored_vtable =
934 { { &manager_type::manage }, &invoker_type::invoke };
935
936 if (stored_vtable.assign_to(f, functor)) {
937 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
938 if (ndnboost::has_trivial_copy_constructor<Functor>::value &&
939 ndnboost::has_trivial_destructor<Functor>::value &&
940 detail::function::function_allows_small_object_optimization<Functor>::value)
941 value |= static_cast<size_t>(0x01);
942 vtable = reinterpret_cast<detail::function::vtable_base *>(value);
943 } else
944 vtable = 0;
945 }
946
947 template<typename Functor,typename Allocator>
948 void assign_to_a(Functor f,Allocator a)
949 {
950 using detail::function::vtable_base;
951
952 typedef typename detail::function::get_function_tag<Functor>::type tag;
953 typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
954 typedef typename get_invoker::
955 template apply_a<Functor, R BOOST_FUNCTION_COMMA
956 BOOST_FUNCTION_TEMPLATE_ARGS,
957 Allocator>
958 handler_type;
959
960 typedef typename handler_type::invoker_type invoker_type;
961 typedef typename handler_type::manager_type manager_type;
962
963 // Note: it is extremely important that this initialization use
964 // static initialization. Otherwise, we will have a race
965 // condition here in multi-threaded code. See
966 // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
967 static const vtable_type stored_vtable =
968 { { &manager_type::manage }, &invoker_type::invoke };
969
970 if (stored_vtable.assign_to_a(f, functor, a)) {
971 std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
972 if (ndnboost::has_trivial_copy_constructor<Functor>::value &&
973 ndnboost::has_trivial_destructor<Functor>::value &&
974 detail::function::function_allows_small_object_optimization<Functor>::value)
975 value |= static_cast<std::size_t>(0x01);
976 vtable = reinterpret_cast<detail::function::vtable_base *>(value);
977 } else
978 vtable = 0;
979 }
980
981 // Moves the value from the specified argument to *this. If the argument
982 // has its function object allocated on the heap, move_assign will pass
983 // its buffer to *this, and set the argument's buffer pointer to NULL.
984 void move_assign(BOOST_FUNCTION_FUNCTION& f)
985 {
986 if (&f == this)
987 return;
988
989 BOOST_TRY {
990 if (!f.empty()) {
991 this->vtable = f.vtable;
992 if (this->has_trivial_copy_and_destroy())
993 this->functor = f.functor;
994 else
995 get_vtable()->base.manager(f.functor, this->functor,
996 ndnboost::detail::function::move_functor_tag);
997 f.vtable = 0;
998 } else {
999 clear();
1000 }
1001 } BOOST_CATCH (...) {
1002 vtable = 0;
1003 BOOST_RETHROW;
1004 }
1005 BOOST_CATCH_END
1006 }
1007 };
1008
1009 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1010 inline void swap(BOOST_FUNCTION_FUNCTION<
1011 R BOOST_FUNCTION_COMMA
1012 BOOST_FUNCTION_TEMPLATE_ARGS
1013 >& f1,
1014 BOOST_FUNCTION_FUNCTION<
1015 R BOOST_FUNCTION_COMMA
1016 BOOST_FUNCTION_TEMPLATE_ARGS
1017 >& f2)
1018 {
1019 f1.swap(f2);
1020 }
1021
1022// Poison comparisons between ndnboost::function objects of the same type.
1023template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1024 void operator==(const BOOST_FUNCTION_FUNCTION<
1025 R BOOST_FUNCTION_COMMA
1026 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1027 const BOOST_FUNCTION_FUNCTION<
1028 R BOOST_FUNCTION_COMMA
1029 BOOST_FUNCTION_TEMPLATE_ARGS>&);
1030template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1031 void operator!=(const BOOST_FUNCTION_FUNCTION<
1032 R BOOST_FUNCTION_COMMA
1033 BOOST_FUNCTION_TEMPLATE_ARGS>&,
1034 const BOOST_FUNCTION_FUNCTION<
1035 R BOOST_FUNCTION_COMMA
1036 BOOST_FUNCTION_TEMPLATE_ARGS>& );
1037
1038#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1039
1040#if BOOST_FUNCTION_NUM_ARGS == 0
1041#define BOOST_FUNCTION_PARTIAL_SPEC R (void)
1042#else
1043#define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
1044#endif
1045
1046template<typename R BOOST_FUNCTION_COMMA
1047 BOOST_FUNCTION_TEMPLATE_PARMS>
1048class function<BOOST_FUNCTION_PARTIAL_SPEC>
1049 : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1050{
1051 typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
1052 typedef function self_type;
1053
1054 struct clear_type {};
1055
1056public:
1057
1058 function() : base_type() {}
1059
1060 template<typename Functor>
1061 function(Functor f
1062#ifndef BOOST_NO_SFINAE
1063 ,typename enable_if_c<
1064 (ndnboost::type_traits::ice_not<
1065 (is_integral<Functor>::value)>::value),
1066 int>::type = 0
1067#endif
1068 ) :
1069 base_type(f)
1070 {
1071 }
1072 template<typename Functor,typename Allocator>
1073 function(Functor f, Allocator a
1074#ifndef BOOST_NO_SFINAE
1075 ,typename enable_if_c<
1076 (ndnboost::type_traits::ice_not<
1077 (is_integral<Functor>::value)>::value),
1078 int>::type = 0
1079#endif
1080 ) :
1081 base_type(f,a)
1082 {
1083 }
1084
1085#ifndef BOOST_NO_SFINAE
1086 function(clear_type*) : base_type() {}
1087#endif
1088
1089 function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1090
1091 function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1092
1093#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1094 // Move constructors
1095 function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
1096 function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
1097#endif
1098
1099 self_type& operator=(const self_type& f)
1100 {
1101 self_type(f).swap(*this);
1102 return *this;
1103 }
1104
1105#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1106 self_type& operator=(self_type&& f)
1107 {
1108 self_type(static_cast<self_type&&>(f)).swap(*this);
1109 return *this;
1110 }
1111#endif
1112
1113 template<typename Functor>
1114#ifndef BOOST_NO_SFINAE
1115 typename enable_if_c<
1116 (ndnboost::type_traits::ice_not<
1117 (is_integral<Functor>::value)>::value),
1118 self_type&>::type
1119#else
1120 self_type&
1121#endif
1122 operator=(Functor f)
1123 {
1124 self_type(f).swap(*this);
1125 return *this;
1126 }
1127
1128#ifndef BOOST_NO_SFINAE
1129 self_type& operator=(clear_type*)
1130 {
1131 this->clear();
1132 return *this;
1133 }
1134#endif
1135
1136 self_type& operator=(const base_type& f)
1137 {
1138 self_type(f).swap(*this);
1139 return *this;
1140 }
1141
1142#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1143 self_type& operator=(base_type&& f)
1144 {
1145 self_type(static_cast<base_type&&>(f)).swap(*this);
1146 return *this;
1147 }
1148#endif
1149};
1150
1151#undef BOOST_FUNCTION_PARTIAL_SPEC
1152#endif // have partial specialization
1153
1154} // end namespace ndnboost
1155
1156// Cleanup after ourselves...
1157#undef BOOST_FUNCTION_VTABLE
1158#undef BOOST_FUNCTION_COMMA
1159#undef BOOST_FUNCTION_FUNCTION
1160#undef BOOST_FUNCTION_FUNCTION_INVOKER
1161#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
1162#undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
1163#undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
1164#undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
1165#undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
1166#undef BOOST_FUNCTION_MEMBER_INVOKER
1167#undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
1168#undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
1169#undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
1170#undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
1171#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
1172#undef BOOST_FUNCTION_GET_INVOKER
1173#undef BOOST_FUNCTION_TEMPLATE_PARMS
1174#undef BOOST_FUNCTION_TEMPLATE_ARGS
1175#undef BOOST_FUNCTION_PARMS
1176#undef BOOST_FUNCTION_PARM
1177#undef BOOST_FUNCTION_ARGS
1178#undef BOOST_FUNCTION_ARG_TYPE
1179#undef BOOST_FUNCTION_ARG_TYPES
1180#undef BOOST_FUNCTION_VOID_RETURN_TYPE
1181#undef BOOST_FUNCTION_RETURN
1182
1183#if defined(BOOST_MSVC)
1184# pragma warning( pop )
1185#endif