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