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