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