]> git.lyx.org Git - features.git/blob - 3rdparty/boost/boost/function/function_template.hpp
Update local boost version to version 1.62
[features.git] / 3rdparty / 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           typedef typename Allocator::template rebind<functor_wrapper_type>::other
594             wrapper_allocator_type;
595           typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
596           wrapper_allocator_type wrapper_allocator(a);
597           wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
598           wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
599           functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
600           functor.members.obj_ptr = new_f;
601         }
602
603         template<typename FunctionObj>
604         bool
605         assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
606         {
607           if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
608             assign_functor(f, functor,
609                            mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
610             return true;
611           } else {
612             return false;
613           }
614         }
615         template<typename FunctionObj,typename Allocator>
616         bool
617         assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
618         {
619           if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
620             assign_functor_a(f, functor, a,
621                            mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
622             return true;
623           } else {
624             return false;
625           }
626         }
627
628         // Reference to a function object
629         template<typename FunctionObj>
630         bool
631         assign_to(const reference_wrapper<FunctionObj>& f,
632                   function_buffer& functor, function_obj_ref_tag) const
633         {
634           functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer());
635           functor.members.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
636           functor.members.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
637           return true;
638         }
639         template<typename FunctionObj,typename Allocator>
640         bool
641         assign_to_a(const reference_wrapper<FunctionObj>& f,
642                   function_buffer& functor, Allocator, function_obj_ref_tag) const
643         {
644           return assign_to(f,functor,function_obj_ref_tag());
645         }
646
647       public:
648         vtable_base base;
649         invoker_type invoker;
650       };
651     } // end namespace function
652   } // end namespace detail
653
654   template<
655     typename R BOOST_FUNCTION_COMMA
656     BOOST_FUNCTION_TEMPLATE_PARMS
657   >
658   class BOOST_FUNCTION_FUNCTION : public function_base
659
660 #if BOOST_FUNCTION_NUM_ARGS == 1
661
662     , public std::unary_function<T0,R>
663
664 #elif BOOST_FUNCTION_NUM_ARGS == 2
665
666     , public std::binary_function<T0,T1,R>
667
668 #endif
669
670   {
671   public:
672 #ifndef BOOST_NO_VOID_RETURNS
673     typedef R         result_type;
674 #else
675     typedef  typename boost::detail::function::function_return_type<R>::type
676       result_type;
677 #endif // BOOST_NO_VOID_RETURNS
678
679   private:
680     typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
681               R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
682       vtable_type;
683
684     vtable_type* get_vtable() const {
685       return reinterpret_cast<vtable_type*>(
686                reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
687     }
688
689     struct clear_type {};
690
691   public:
692     BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
693
694     // add signature for boost::lambda
695     template<typename Args>
696     struct sig
697     {
698       typedef result_type type;
699     };
700
701 #if BOOST_FUNCTION_NUM_ARGS == 1
702     typedef T0 argument_type;
703 #elif BOOST_FUNCTION_NUM_ARGS == 2
704     typedef T0 first_argument_type;
705     typedef T1 second_argument_type;
706 #endif
707
708     BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
709     BOOST_FUNCTION_ARG_TYPES
710
711     typedef BOOST_FUNCTION_FUNCTION self_type;
712
713     BOOST_FUNCTION_FUNCTION() : function_base() { }
714
715     // MSVC chokes if the following two constructors are collapsed into
716     // one with a default parameter.
717     template<typename Functor>
718     BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
719 #ifndef BOOST_NO_SFINAE
720                             ,typename boost::enable_if_c<
721                              !(is_integral<Functor>::value),
722                                         int>::type = 0
723 #endif // BOOST_NO_SFINAE
724                             ) :
725       function_base()
726     {
727       this->assign_to(f);
728     }
729     template<typename Functor,typename Allocator>
730     BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
731 #ifndef BOOST_NO_SFINAE
732                             ,typename boost::enable_if_c<
733                               !(is_integral<Functor>::value),
734                                         int>::type = 0
735 #endif // BOOST_NO_SFINAE
736                             ) :
737       function_base()
738     {
739       this->assign_to_a(f,a);
740     }
741
742 #ifndef BOOST_NO_SFINAE
743     BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
744 #else
745     BOOST_FUNCTION_FUNCTION(int zero) : function_base()
746     {
747       BOOST_ASSERT(zero == 0);
748     }
749 #endif
750
751     BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
752     {
753       this->assign_to_own(f);
754     }
755
756 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
757     BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
758     {
759       this->move_assign(f);
760     }
761 #endif
762
763     ~BOOST_FUNCTION_FUNCTION() { clear(); }
764
765     result_type operator()(BOOST_FUNCTION_PARMS) const
766     {
767       if (this->empty())
768         boost::throw_exception(bad_function_call());
769
770       return get_vtable()->invoker
771                (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
772     }
773
774     // The distinction between when to use BOOST_FUNCTION_FUNCTION and
775     // when to use self_type is obnoxious. MSVC cannot handle self_type as
776     // the return type of these assignment operators, but Borland C++ cannot
777     // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
778     // construct.
779     template<typename Functor>
780 #ifndef BOOST_NO_SFINAE
781     typename boost::enable_if_c<
782                   !(is_integral<Functor>::value),
783                BOOST_FUNCTION_FUNCTION&>::type
784 #else
785     BOOST_FUNCTION_FUNCTION&
786 #endif
787     operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
788     {
789       this->clear();
790       BOOST_TRY  {
791         this->assign_to(f);
792       } BOOST_CATCH (...) {
793         vtable = 0;
794         BOOST_RETHROW;
795       }
796       BOOST_CATCH_END
797       return *this;
798     }
799     template<typename Functor,typename Allocator>
800     void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
801     {
802       this->clear();
803       BOOST_TRY{
804         this->assign_to_a(f,a);
805       } BOOST_CATCH (...) {
806         vtable = 0;
807         BOOST_RETHROW;
808       }
809       BOOST_CATCH_END
810     }
811
812 #ifndef BOOST_NO_SFINAE
813     BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
814     {
815       this->clear();
816       return *this;
817     }
818 #else
819     BOOST_FUNCTION_FUNCTION& operator=(int zero)
820     {
821       BOOST_ASSERT(zero == 0);
822       this->clear();
823       return *this;
824     }
825 #endif
826
827     // Assignment from another BOOST_FUNCTION_FUNCTION
828     BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
829     {
830       if (&f == this)
831         return *this;
832
833       this->clear();
834       BOOST_TRY {
835         this->assign_to_own(f);
836       } BOOST_CATCH (...) {
837         vtable = 0;
838         BOOST_RETHROW;
839       }
840       BOOST_CATCH_END
841       return *this;
842     }
843
844 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
845     // Move assignment from another BOOST_FUNCTION_FUNCTION
846     BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
847     {
848       if (&f == this)
849         return *this;
850
851       this->clear();
852       BOOST_TRY {
853         this->move_assign(f);
854       } BOOST_CATCH (...) {
855         vtable = 0;
856         BOOST_RETHROW;
857       }
858       BOOST_CATCH_END
859       return *this;
860     }
861 #endif
862
863     void swap(BOOST_FUNCTION_FUNCTION& other)
864     {
865       if (&other == this)
866         return;
867
868       BOOST_FUNCTION_FUNCTION tmp;
869       tmp.move_assign(*this);
870       this->move_assign(other);
871       other.move_assign(tmp);
872     }
873
874     // Clear out a target, if there is one
875     void clear()
876     {
877       if (vtable) {
878         if (!this->has_trivial_copy_and_destroy())
879           get_vtable()->clear(this->functor);
880         vtable = 0;
881       }
882     }
883
884 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
885     // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
886     operator bool () const { return !this->empty(); }
887 #else
888   private:
889     struct dummy {
890       void nonnull() {}
891     };
892
893     typedef void (dummy::*safe_bool)();
894
895   public:
896     operator safe_bool () const
897       { return (this->empty())? 0 : &dummy::nonnull; }
898
899     bool operator!() const
900       { return this->empty(); }
901 #endif
902
903   private:
904     void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
905     {
906       if (!f.empty()) {
907         this->vtable = f.vtable;
908         if (this->has_trivial_copy_and_destroy())
909           this->functor = f.functor;
910         else
911           get_vtable()->base.manager(f.functor, this->functor,
912                                      boost::detail::function::clone_functor_tag);
913       }
914     }
915
916     template<typename Functor>
917     void assign_to(Functor f)
918     {
919       using boost::detail::function::vtable_base;
920
921       typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
922       typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
923       typedef typename get_invoker::
924                          template apply<Functor, R BOOST_FUNCTION_COMMA
925                         BOOST_FUNCTION_TEMPLATE_ARGS>
926         handler_type;
927
928       typedef typename handler_type::invoker_type invoker_type;
929       typedef typename handler_type::manager_type manager_type;
930
931       // Note: it is extremely important that this initialization use
932       // static initialization. Otherwise, we will have a race
933       // condition here in multi-threaded code. See
934       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
935       static const vtable_type stored_vtable =
936         { { &manager_type::manage }, &invoker_type::invoke };
937
938       if (stored_vtable.assign_to(f, functor)) {
939         std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
940         // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
941         if (boost::has_trivial_copy_constructor<Functor>::value &&
942             boost::has_trivial_destructor<Functor>::value &&
943             boost::detail::function::function_allows_small_object_optimization<Functor>::value)
944           value |= static_cast<std::size_t>(0x01);
945         vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
946       } else
947         vtable = 0;
948     }
949
950     template<typename Functor,typename Allocator>
951     void assign_to_a(Functor f,Allocator a)
952     {
953       using boost::detail::function::vtable_base;
954
955       typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
956       typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
957       typedef typename get_invoker::
958                          template apply_a<Functor, R BOOST_FUNCTION_COMMA
959                          BOOST_FUNCTION_TEMPLATE_ARGS,
960                          Allocator>
961         handler_type;
962
963       typedef typename handler_type::invoker_type invoker_type;
964       typedef typename handler_type::manager_type manager_type;
965
966       // Note: it is extremely important that this initialization use
967       // static initialization. Otherwise, we will have a race
968       // condition here in multi-threaded code. See
969       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
970       static const vtable_type stored_vtable =
971         { { &manager_type::manage }, &invoker_type::invoke };
972
973       if (stored_vtable.assign_to_a(f, functor, a)) {
974         std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
975         // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
976         if (boost::has_trivial_copy_constructor<Functor>::value &&
977             boost::has_trivial_destructor<Functor>::value &&
978             boost::detail::function::function_allows_small_object_optimization<Functor>::value)
979           value |= static_cast<std::size_t>(0x01);
980         vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
981       } else
982         vtable = 0;
983     }
984
985     // Moves the value from the specified argument to *this. If the argument
986     // has its function object allocated on the heap, move_assign will pass
987     // its buffer to *this, and set the argument's buffer pointer to NULL.
988     void move_assign(BOOST_FUNCTION_FUNCTION& f)
989     {
990       if (&f == this)
991         return;
992
993       BOOST_TRY {
994         if (!f.empty()) {
995           this->vtable = f.vtable;
996           if (this->has_trivial_copy_and_destroy())
997             this->functor = f.functor;
998           else
999             get_vtable()->base.manager(f.functor, this->functor,
1000                                      boost::detail::function::move_functor_tag);
1001           f.vtable = 0;
1002         } else {
1003           clear();
1004         }
1005       } BOOST_CATCH (...) {
1006         vtable = 0;
1007         BOOST_RETHROW;
1008       }
1009       BOOST_CATCH_END
1010     }
1011   };
1012
1013   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1014   inline void swap(BOOST_FUNCTION_FUNCTION<
1015                      R BOOST_FUNCTION_COMMA
1016                      BOOST_FUNCTION_TEMPLATE_ARGS
1017                    >& f1,
1018                    BOOST_FUNCTION_FUNCTION<
1019                      R BOOST_FUNCTION_COMMA
1020                      BOOST_FUNCTION_TEMPLATE_ARGS
1021                    >& f2)
1022   {
1023     f1.swap(f2);
1024   }
1025
1026 // Poison comparisons between boost::function objects of the same type.
1027 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1028   void operator==(const BOOST_FUNCTION_FUNCTION<
1029                           R BOOST_FUNCTION_COMMA
1030                           BOOST_FUNCTION_TEMPLATE_ARGS>&,
1031                   const BOOST_FUNCTION_FUNCTION<
1032                           R BOOST_FUNCTION_COMMA
1033                           BOOST_FUNCTION_TEMPLATE_ARGS>&);
1034 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1035   void operator!=(const BOOST_FUNCTION_FUNCTION<
1036                           R BOOST_FUNCTION_COMMA
1037                           BOOST_FUNCTION_TEMPLATE_ARGS>&,
1038                   const BOOST_FUNCTION_FUNCTION<
1039                           R BOOST_FUNCTION_COMMA
1040                           BOOST_FUNCTION_TEMPLATE_ARGS>& );
1041
1042 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1043
1044 #if BOOST_FUNCTION_NUM_ARGS == 0
1045 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
1046 #else
1047 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
1048 #endif
1049
1050 template<typename R BOOST_FUNCTION_COMMA
1051          BOOST_FUNCTION_TEMPLATE_PARMS>
1052 class function<BOOST_FUNCTION_PARTIAL_SPEC>
1053   : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1054 {
1055   typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
1056   typedef function self_type;
1057
1058   struct clear_type {};
1059
1060 public:
1061
1062   function() : base_type() {}
1063
1064   template<typename Functor>
1065   function(Functor f
1066 #ifndef BOOST_NO_SFINAE
1067            ,typename boost::enable_if_c<
1068                           !(is_integral<Functor>::value),
1069                        int>::type = 0
1070 #endif
1071            ) :
1072     base_type(f)
1073   {
1074   }
1075   template<typename Functor,typename Allocator>
1076   function(Functor f, Allocator a
1077 #ifndef BOOST_NO_SFINAE
1078            ,typename boost::enable_if_c<
1079                            !(is_integral<Functor>::value),
1080                        int>::type = 0
1081 #endif
1082            ) :
1083     base_type(f,a)
1084   {
1085   }
1086
1087 #ifndef BOOST_NO_SFINAE
1088   function(clear_type*) : base_type() {}
1089 #endif
1090
1091   function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1092
1093   function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1094
1095 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1096   // Move constructors
1097   function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
1098   function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
1099 #endif
1100
1101   self_type& operator=(const self_type& f)
1102   {
1103     self_type(f).swap(*this);
1104     return *this;
1105   }
1106
1107 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1108   self_type& operator=(self_type&& f)
1109   {
1110     self_type(static_cast<self_type&&>(f)).swap(*this);
1111     return *this;
1112   }
1113 #endif
1114
1115   template<typename Functor>
1116 #ifndef BOOST_NO_SFINAE
1117   typename boost::enable_if_c<
1118                          !(is_integral<Functor>::value),
1119                       self_type&>::type
1120 #else
1121   self_type&
1122 #endif
1123   operator=(Functor f)
1124   {
1125     self_type(f).swap(*this);
1126     return *this;
1127   }
1128
1129 #ifndef BOOST_NO_SFINAE
1130   self_type& operator=(clear_type*)
1131   {
1132     this->clear();
1133     return *this;
1134   }
1135 #endif
1136
1137   self_type& operator=(const base_type& f)
1138   {
1139     self_type(f).swap(*this);
1140     return *this;
1141   }
1142
1143 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1144   self_type& operator=(base_type&& f)
1145   {
1146     self_type(static_cast<base_type&&>(f)).swap(*this);
1147     return *this;
1148   }
1149 #endif
1150 };
1151
1152 #undef BOOST_FUNCTION_PARTIAL_SPEC
1153 #endif // have partial specialization
1154
1155 } // end namespace boost
1156
1157 // Cleanup after ourselves...
1158 #undef BOOST_FUNCTION_VTABLE
1159 #undef BOOST_FUNCTION_COMMA
1160 #undef BOOST_FUNCTION_FUNCTION
1161 #undef BOOST_FUNCTION_FUNCTION_INVOKER
1162 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
1163 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
1164 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
1165 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
1166 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
1167 #undef BOOST_FUNCTION_MEMBER_INVOKER
1168 #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
1169 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
1170 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
1171 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
1172 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
1173 #undef BOOST_FUNCTION_GET_INVOKER
1174 #undef BOOST_FUNCTION_TEMPLATE_PARMS
1175 #undef BOOST_FUNCTION_TEMPLATE_ARGS
1176 #undef BOOST_FUNCTION_PARMS
1177 #undef BOOST_FUNCTION_PARM
1178 #ifdef BOOST_FUNCTION_ARG
1179 #   undef BOOST_FUNCTION_ARG
1180 #endif
1181 #undef BOOST_FUNCTION_ARGS
1182 #undef BOOST_FUNCTION_ARG_TYPE
1183 #undef BOOST_FUNCTION_ARG_TYPES
1184 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
1185 #undef BOOST_FUNCTION_RETURN
1186
1187 #if defined(BOOST_MSVC)
1188 #   pragma warning( pop )
1189 #endif