]> git.lyx.org Git - lyx.git/blob - boost/boost/function/function_template.hpp
Cmake export tests: More tests to be inverted, suspended or made non-standard
[lyx.git] / 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.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.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.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.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.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.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.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.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.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.obj_ref.obj_ptr = (void *)(f.get_pointer());
635           functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
636           functor.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       
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           this->functor = f.functor;
911         else
912           get_vtable()->base.manager(f.functor, this->functor,
913                                      boost::detail::function::clone_functor_tag);
914       }
915     }
916
917     template<typename Functor>
918     void assign_to(Functor f)
919     {
920       using boost::detail::function::vtable_base;
921
922       typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
923       typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
924       typedef typename get_invoker::
925                          template apply<Functor, R BOOST_FUNCTION_COMMA 
926                         BOOST_FUNCTION_TEMPLATE_ARGS>
927         handler_type;
928       
929       typedef typename handler_type::invoker_type invoker_type;
930       typedef typename handler_type::manager_type manager_type;
931
932       // Note: it is extremely important that this initialization use
933       // static initialization. Otherwise, we will have a race
934       // condition here in multi-threaded code. See
935       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
936       static const vtable_type stored_vtable = 
937         { { &manager_type::manage }, &invoker_type::invoke };
938
939       if (stored_vtable.assign_to(f, functor)) {
940         std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
941         // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
942         if (boost::has_trivial_copy_constructor<Functor>::value &&
943             boost::has_trivial_destructor<Functor>::value &&
944             boost::detail::function::function_allows_small_object_optimization<Functor>::value)
945           value |= static_cast<std::size_t>(0x01);
946         vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
947       } else 
948         vtable = 0;
949     }
950
951     template<typename Functor,typename Allocator>
952     void assign_to_a(Functor f,Allocator a)
953     {
954       using boost::detail::function::vtable_base;
955
956       typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
957       typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
958       typedef typename get_invoker::
959                          template apply_a<Functor, R BOOST_FUNCTION_COMMA 
960                          BOOST_FUNCTION_TEMPLATE_ARGS,
961                          Allocator>
962         handler_type;
963       
964       typedef typename handler_type::invoker_type invoker_type;
965       typedef typename handler_type::manager_type manager_type;
966
967       // Note: it is extremely important that this initialization use
968       // static initialization. Otherwise, we will have a race
969       // condition here in multi-threaded code. See
970       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
971       static const vtable_type stored_vtable =
972         { { &manager_type::manage }, &invoker_type::invoke };
973
974       if (stored_vtable.assign_to_a(f, functor, a)) { 
975         std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
976         // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
977         if (boost::has_trivial_copy_constructor<Functor>::value &&
978             boost::has_trivial_destructor<Functor>::value &&
979             boost::detail::function::function_allows_small_object_optimization<Functor>::value)
980           value |= static_cast<std::size_t>(0x01);
981         vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
982       } else 
983         vtable = 0;
984     }
985
986     // Moves the value from the specified argument to *this. If the argument 
987     // has its function object allocated on the heap, move_assign will pass 
988     // its buffer to *this, and set the argument's buffer pointer to NULL. 
989     void move_assign(BOOST_FUNCTION_FUNCTION& f) 
990     { 
991       if (&f == this)
992         return;
993
994       BOOST_TRY {
995         if (!f.empty()) {
996           this->vtable = f.vtable;
997           if (this->has_trivial_copy_and_destroy())
998             this->functor = f.functor;
999           else
1000             get_vtable()->base.manager(f.functor, this->functor,
1001                                      boost::detail::function::move_functor_tag);
1002           f.vtable = 0;
1003         } else {
1004           clear();
1005         }
1006       } BOOST_CATCH (...) {
1007         vtable = 0;
1008         BOOST_RETHROW;
1009       }
1010       BOOST_CATCH_END
1011     }
1012   };
1013
1014   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1015   inline void swap(BOOST_FUNCTION_FUNCTION<
1016                      R BOOST_FUNCTION_COMMA
1017                      BOOST_FUNCTION_TEMPLATE_ARGS
1018                    >& f1,
1019                    BOOST_FUNCTION_FUNCTION<
1020                      R BOOST_FUNCTION_COMMA
1021                      BOOST_FUNCTION_TEMPLATE_ARGS
1022                    >& f2)
1023   {
1024     f1.swap(f2);
1025   }
1026
1027 // Poison comparisons between boost::function objects of the same type.
1028 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1029   void operator==(const BOOST_FUNCTION_FUNCTION<
1030                           R BOOST_FUNCTION_COMMA
1031                           BOOST_FUNCTION_TEMPLATE_ARGS>&,
1032                   const BOOST_FUNCTION_FUNCTION<
1033                           R BOOST_FUNCTION_COMMA
1034                           BOOST_FUNCTION_TEMPLATE_ARGS>&);
1035 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1036   void operator!=(const BOOST_FUNCTION_FUNCTION<
1037                           R BOOST_FUNCTION_COMMA
1038                           BOOST_FUNCTION_TEMPLATE_ARGS>&,
1039                   const BOOST_FUNCTION_FUNCTION<
1040                           R BOOST_FUNCTION_COMMA
1041                           BOOST_FUNCTION_TEMPLATE_ARGS>& );
1042
1043 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1044
1045 #if BOOST_FUNCTION_NUM_ARGS == 0
1046 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
1047 #else
1048 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
1049 #endif
1050
1051 template<typename R BOOST_FUNCTION_COMMA
1052          BOOST_FUNCTION_TEMPLATE_PARMS>
1053 class function<BOOST_FUNCTION_PARTIAL_SPEC>
1054   : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1055 {
1056   typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
1057   typedef function self_type;
1058
1059   struct clear_type {};
1060
1061 public:
1062
1063   function() : base_type() {}
1064
1065   template<typename Functor>
1066   function(Functor f
1067 #ifndef BOOST_NO_SFINAE
1068            ,typename boost::enable_if_c<
1069                           !(is_integral<Functor>::value),
1070                        int>::type = 0
1071 #endif
1072            ) :
1073     base_type(f)
1074   {
1075   }
1076   template<typename Functor,typename Allocator>
1077   function(Functor f, Allocator a
1078 #ifndef BOOST_NO_SFINAE
1079            ,typename boost::enable_if_c<
1080                            !(is_integral<Functor>::value),
1081                        int>::type = 0
1082 #endif
1083            ) :
1084     base_type(f,a)
1085   {
1086   }
1087
1088 #ifndef BOOST_NO_SFINAE
1089   function(clear_type*) : base_type() {}
1090 #endif
1091
1092   function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1093
1094   function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1095
1096 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1097   // Move constructors
1098   function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
1099   function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
1100 #endif
1101   
1102   self_type& operator=(const self_type& f)
1103   {
1104     self_type(f).swap(*this);
1105     return *this;
1106   }
1107
1108 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1109   self_type& operator=(self_type&& f)
1110   {
1111     self_type(static_cast<self_type&&>(f)).swap(*this);
1112     return *this;
1113   }
1114 #endif  
1115
1116   template<typename Functor>
1117 #ifndef BOOST_NO_SFINAE
1118   typename boost::enable_if_c<
1119                          !(is_integral<Functor>::value),
1120                       self_type&>::type
1121 #else
1122   self_type&
1123 #endif
1124   operator=(Functor f)
1125   {
1126     self_type(f).swap(*this);
1127     return *this;
1128   }
1129
1130 #ifndef BOOST_NO_SFINAE
1131   self_type& operator=(clear_type*)
1132   {
1133     this->clear();
1134     return *this;
1135   }
1136 #endif
1137
1138   self_type& operator=(const base_type& f)
1139   {
1140     self_type(f).swap(*this);
1141     return *this;
1142   }
1143   
1144 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1145   self_type& operator=(base_type&& f)
1146   {
1147     self_type(static_cast<base_type&&>(f)).swap(*this);
1148     return *this;
1149   }
1150 #endif 
1151 };
1152
1153 #undef BOOST_FUNCTION_PARTIAL_SPEC
1154 #endif // have partial specialization
1155
1156 } // end namespace boost
1157
1158 // Cleanup after ourselves...
1159 #undef BOOST_FUNCTION_VTABLE
1160 #undef BOOST_FUNCTION_COMMA
1161 #undef BOOST_FUNCTION_FUNCTION
1162 #undef BOOST_FUNCTION_FUNCTION_INVOKER
1163 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
1164 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
1165 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
1166 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
1167 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
1168 #undef BOOST_FUNCTION_MEMBER_INVOKER
1169 #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
1170 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
1171 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
1172 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
1173 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
1174 #undef BOOST_FUNCTION_GET_INVOKER
1175 #undef BOOST_FUNCTION_TEMPLATE_PARMS
1176 #undef BOOST_FUNCTION_TEMPLATE_ARGS
1177 #undef BOOST_FUNCTION_PARMS
1178 #undef BOOST_FUNCTION_PARM
1179 #ifdef BOOST_FUNCTION_ARG
1180 #   undef BOOST_FUNCTION_ARG
1181 #endif
1182 #undef BOOST_FUNCTION_ARGS
1183 #undef BOOST_FUNCTION_ARG_TYPE
1184 #undef BOOST_FUNCTION_ARG_TYPES
1185 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
1186 #undef BOOST_FUNCTION_RETURN
1187
1188 #if defined(BOOST_MSVC)
1189 #   pragma warning( pop )
1190 #endif