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