]> git.lyx.org Git - lyx.git/blob - boost/boost/function/function_template.hpp
update boost to version 1.36
[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_GET_FUNCTION_INVOKER \
57   BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
58 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
59   BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
60 #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
61   BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
62 #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
63
64 #ifndef BOOST_NO_VOID_RETURNS
65 #  define BOOST_FUNCTION_VOID_RETURN_TYPE void
66 #  define BOOST_FUNCTION_RETURN(X) X
67 #else
68 #  define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable
69 #  define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
70 #endif
71
72 namespace boost {
73   namespace detail {
74     namespace function {
75       template<
76         typename FunctionPtr,
77         typename R BOOST_FUNCTION_COMMA
78         BOOST_FUNCTION_TEMPLATE_PARMS
79         >
80       struct BOOST_FUNCTION_FUNCTION_INVOKER
81       {
82         static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
83                         BOOST_FUNCTION_PARMS)
84         {
85           FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
86           return f(BOOST_FUNCTION_ARGS);
87         }
88       };
89
90       template<
91         typename FunctionPtr,
92         typename R BOOST_FUNCTION_COMMA
93         BOOST_FUNCTION_TEMPLATE_PARMS
94         >
95       struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
96       {
97         static BOOST_FUNCTION_VOID_RETURN_TYPE
98         invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
99                BOOST_FUNCTION_PARMS)
100
101         {
102           FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
103           BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
104         }
105       };
106
107       template<
108         typename FunctionObj,
109         typename R BOOST_FUNCTION_COMMA
110         BOOST_FUNCTION_TEMPLATE_PARMS
111       >
112       struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
113       {
114         static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
115                         BOOST_FUNCTION_PARMS)
116
117         {
118           FunctionObj* f;
119           if (function_allows_small_object_optimization<FunctionObj>::value)
120             f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
121           else
122             f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
123           return (*f)(BOOST_FUNCTION_ARGS);
124         }
125       };
126
127       template<
128         typename FunctionObj,
129         typename R BOOST_FUNCTION_COMMA
130         BOOST_FUNCTION_TEMPLATE_PARMS
131       >
132       struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
133       {
134         static BOOST_FUNCTION_VOID_RETURN_TYPE
135         invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
136                BOOST_FUNCTION_PARMS)
137
138         {
139           FunctionObj* f;
140           if (function_allows_small_object_optimization<FunctionObj>::value)
141             f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
142           else
143             f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
144           BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
145         }
146       };
147
148       template<
149         typename FunctionObj,
150         typename R BOOST_FUNCTION_COMMA
151         BOOST_FUNCTION_TEMPLATE_PARMS
152       >
153       struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
154       {
155         static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
156                         BOOST_FUNCTION_PARMS)
157
158         {
159           FunctionObj* f = 
160             reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
161           return (*f)(BOOST_FUNCTION_ARGS);
162         }
163       };
164
165       template<
166         typename FunctionObj,
167         typename R BOOST_FUNCTION_COMMA
168         BOOST_FUNCTION_TEMPLATE_PARMS
169       >
170       struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
171       {
172         static BOOST_FUNCTION_VOID_RETURN_TYPE
173         invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
174                BOOST_FUNCTION_PARMS)
175
176         {
177           FunctionObj* f = 
178             reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
179           BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
180         }
181       };
182
183       template<
184         typename FunctionPtr,
185         typename R BOOST_FUNCTION_COMMA
186         BOOST_FUNCTION_TEMPLATE_PARMS
187       >
188       struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
189       {
190         typedef typename mpl::if_c<(is_void<R>::value),
191                             BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
192                             FunctionPtr,
193                             R BOOST_FUNCTION_COMMA
194                             BOOST_FUNCTION_TEMPLATE_ARGS
195                           >,
196                           BOOST_FUNCTION_FUNCTION_INVOKER<
197                             FunctionPtr,
198                             R BOOST_FUNCTION_COMMA
199                             BOOST_FUNCTION_TEMPLATE_ARGS
200                           >
201                        >::type type;
202       };
203
204       template<
205         typename FunctionObj,
206         typename R BOOST_FUNCTION_COMMA
207         BOOST_FUNCTION_TEMPLATE_PARMS
208        >
209       struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
210       {
211         typedef typename mpl::if_c<(is_void<R>::value),
212                             BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
213                             FunctionObj,
214                             R BOOST_FUNCTION_COMMA
215                             BOOST_FUNCTION_TEMPLATE_ARGS
216                           >,
217                           BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
218                             FunctionObj,
219                             R BOOST_FUNCTION_COMMA
220                             BOOST_FUNCTION_TEMPLATE_ARGS
221                           >
222                        >::type type;
223       };
224
225       template<
226         typename FunctionObj,
227         typename R BOOST_FUNCTION_COMMA
228         BOOST_FUNCTION_TEMPLATE_PARMS
229        >
230       struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
231       {
232         typedef typename mpl::if_c<(is_void<R>::value),
233                             BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
234                             FunctionObj,
235                             R BOOST_FUNCTION_COMMA
236                             BOOST_FUNCTION_TEMPLATE_ARGS
237                           >,
238                           BOOST_FUNCTION_FUNCTION_REF_INVOKER<
239                             FunctionObj,
240                             R BOOST_FUNCTION_COMMA
241                             BOOST_FUNCTION_TEMPLATE_ARGS
242                           >
243                        >::type type;
244       };
245
246       /**
247        * vtable for a specific boost::function instance.
248        */
249       template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
250       struct BOOST_FUNCTION_VTABLE : vtable_base
251       {
252 #ifndef BOOST_NO_VOID_RETURNS
253         typedef R         result_type;
254 #else
255         typedef typename function_return_type<R>::type result_type;
256 #endif // BOOST_NO_VOID_RETURNS
257
258         typedef result_type (*invoker_type)(function_buffer&
259                                             BOOST_FUNCTION_COMMA
260                                             BOOST_FUNCTION_TEMPLATE_ARGS);
261
262         template<typename F>
263         BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0)
264         {
265           init(f);
266         }
267         template<typename F,typename Allocator>
268         BOOST_FUNCTION_VTABLE(F f, Allocator) : vtable_base(), invoker(0)
269         {
270           init_a<Allocator>(f);
271         }
272
273         template<typename F>
274         bool assign_to(F f, function_buffer& functor)
275         {
276           typedef typename get_function_tag<F>::type tag;
277           return assign_to(f, functor, tag());
278         }
279         template<typename F,typename Allocator>
280         bool assign_to_a(F f, function_buffer& functor, Allocator a)
281         {
282           typedef typename get_function_tag<F>::type tag;
283           return assign_to_a(f, functor, a, tag());
284         }
285
286         void clear(function_buffer& functor)
287         {
288           if (manager)
289             manager(functor, functor, destroy_functor_tag);
290         }
291
292       private:
293         template<typename F>
294         void init(F f)
295         {
296           typedef typename get_function_tag<F>::type tag;
297           init(f, tag());
298         }
299         template<typename Allocator,typename F>
300         void init_a(F f)
301         {
302           typedef typename get_function_tag<F>::type tag;
303           init_a<Allocator>(f, tag());
304         }
305
306         // Function pointers
307         template<typename FunctionPtr>
308         void init(FunctionPtr /*f*/, function_ptr_tag)
309         {
310           typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
311                              FunctionPtr,
312                              R BOOST_FUNCTION_COMMA
313                              BOOST_FUNCTION_TEMPLATE_ARGS
314                            >::type
315             actual_invoker_type;
316
317           invoker = &actual_invoker_type::invoke;
318           manager = &functor_manager<FunctionPtr>::manage;
319         }
320         template<typename Allocator,typename FunctionPtr>
321         void init_a(FunctionPtr f, function_ptr_tag)
322         {
323           typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
324                              FunctionPtr,
325                              R BOOST_FUNCTION_COMMA
326                              BOOST_FUNCTION_TEMPLATE_ARGS
327                            >::type
328             actual_invoker_type;
329
330           invoker = &actual_invoker_type::invoke;
331           manager = &functor_manager_a<FunctionPtr, Allocator>::manage;
332         }
333
334         template<typename FunctionPtr>
335         bool 
336         assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
337         {
338           this->clear(functor);
339           if (f) {
340             // should be a reinterpret cast, but some compilers insist
341             // on giving cv-qualifiers to free functions
342             functor.func_ptr = (void (*)())(f);
343             return true;
344           } else {
345             return false;
346           }
347         }
348         template<typename FunctionPtr,typename Allocator>
349         bool 
350         assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag)
351         {
352           return assign_to(f,functor,function_ptr_tag());
353         }
354
355         // Member pointers
356 #if BOOST_FUNCTION_NUM_ARGS > 0
357         template<typename MemberPtr>
358         void init(MemberPtr f, member_ptr_tag)
359         {
360           // DPG TBD: Add explicit support for member function
361           // objects, so we invoke through mem_fn() but we retain the
362           // right target_type() values.
363           this->init(mem_fn(f));
364         }
365         template<typename Allocator,typename MemberPtr>
366         void init_a(MemberPtr f, member_ptr_tag)
367         {
368           // DPG TBD: Add explicit support for member function
369           // objects, so we invoke through mem_fn() but we retain the
370           // right target_type() values.
371           this->init_a<Allocator>(mem_fn(f));
372         }
373
374         template<typename MemberPtr>
375         bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag)
376         {
377           // DPG TBD: Add explicit support for member function
378           // objects, so we invoke through mem_fn() but we retain the
379           // right target_type() values.
380           if (f) {
381             this->assign_to(mem_fn(f), functor);
382             return true;
383           } else {
384             return false;
385           }
386         }
387         template<typename MemberPtr,typename Allocator>
388         bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag)
389         {
390           // DPG TBD: Add explicit support for member function
391           // objects, so we invoke through mem_fn() but we retain the
392           // right target_type() values.
393           if (f) {
394             this->assign_to_a(mem_fn(f), functor, a);
395             return true;
396           } else {
397             return false;
398           }
399         }
400 #endif // BOOST_FUNCTION_NUM_ARGS > 0
401
402         // Function objects
403         template<typename FunctionObj>
404         void init(FunctionObj /*f*/, function_obj_tag)
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             actual_invoker_type;
412
413           invoker = &actual_invoker_type::invoke;
414           manager = &functor_manager<FunctionObj>::manage;
415         }
416         template<typename Allocator,typename FunctionObj>
417         void init_a(FunctionObj /*f*/, function_obj_tag)
418         {
419           typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
420                              FunctionObj,
421                              R BOOST_FUNCTION_COMMA
422                              BOOST_FUNCTION_TEMPLATE_ARGS
423                            >::type
424             actual_invoker_type;
425
426           invoker = &actual_invoker_type::invoke;
427           manager = &functor_manager_a<FunctionObj, Allocator>::manage;
428         }
429
430         // Assign to a function object using the small object optimization
431         template<typename FunctionObj>
432         void 
433         assign_functor(FunctionObj f, function_buffer& functor, mpl::true_)
434         {
435           new ((void*)&functor.data) FunctionObj(f);
436         }
437         template<typename FunctionObj,typename Allocator>
438         void 
439         assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_)
440         {
441           assign_functor(f,functor,mpl::true_());
442         }
443
444         // Assign to a function object allocated on the heap.
445         template<typename FunctionObj>
446         void 
447         assign_functor(FunctionObj f, function_buffer& functor, mpl::false_)
448         {
449           functor.obj_ptr = new FunctionObj(f);
450         }
451         template<typename FunctionObj,typename Allocator>
452         void 
453         assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_)
454         {
455           typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
456           typedef typename Allocator::template rebind<functor_wrapper_type>::other
457             wrapper_allocator_type;
458           typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
459           wrapper_allocator_type wrapper_allocator(a);
460           wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
461           wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
462           functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
463           functor.obj_ptr = new_f;
464         }
465
466         template<typename FunctionObj>
467         bool 
468         assign_to(FunctionObj f, function_buffer& functor, function_obj_tag)
469         {
470           if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
471             assign_functor(f, functor, 
472                            mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
473             return true;
474           } else {
475             return false;
476           }
477         }
478         template<typename FunctionObj,typename Allocator>
479         bool 
480         assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag)
481         {
482           if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
483             assign_functor_a(f, functor, a,
484                            mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
485             return true;
486           } else {
487             return false;
488           }
489         }
490
491         // Reference to a function object
492         template<typename FunctionObj>
493         void 
494         init(const reference_wrapper<FunctionObj>& /*f*/, function_obj_ref_tag)
495         {
496           typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
497                              FunctionObj,
498                              R BOOST_FUNCTION_COMMA
499                              BOOST_FUNCTION_TEMPLATE_ARGS
500                            >::type
501             actual_invoker_type;
502
503           invoker = &actual_invoker_type::invoke;
504           manager = &reference_manager<FunctionObj>::get;
505         }
506         template<typename Allocator,typename FunctionObj>
507         void 
508         init_a(const reference_wrapper<FunctionObj>& f, function_obj_ref_tag)
509         {
510           init(f,function_obj_ref_tag());
511         }
512
513         template<typename FunctionObj>
514         bool 
515         assign_to(const reference_wrapper<FunctionObj>& f, 
516                   function_buffer& functor, function_obj_ref_tag)
517         {
518           if (!boost::detail::function::has_empty_target(f.get_pointer())) {
519             // DPG TBD: We might need to detect constness of
520             // FunctionObj to assign into obj_ptr or const_obj_ptr to
521             // be truly legit, but no platform in existence makes
522             // const void* different from void*.
523             functor.const_obj_ptr = f.get_pointer();
524             return true;
525           } else {
526             return false;
527           }
528         }
529         template<typename FunctionObj,typename Allocator>
530         bool 
531         assign_to_a(const reference_wrapper<FunctionObj>& f, 
532                   function_buffer& functor, Allocator, function_obj_ref_tag)
533         {
534           return assign_to(f,functor,function_obj_ref_tag());
535         }
536
537       public:
538         invoker_type invoker;
539       };
540     } // end namespace function
541   } // end namespace detail
542
543   template<
544     typename R BOOST_FUNCTION_COMMA
545     BOOST_FUNCTION_TEMPLATE_PARMS
546   >
547   class BOOST_FUNCTION_FUNCTION : public function_base
548
549 #if BOOST_FUNCTION_NUM_ARGS == 1
550
551     , public std::unary_function<T0,R>
552
553 #elif BOOST_FUNCTION_NUM_ARGS == 2
554
555     , public std::binary_function<T0,T1,R>
556
557 #endif
558
559   {
560   public:
561 #ifndef BOOST_NO_VOID_RETURNS
562     typedef R         result_type;
563 #else
564     typedef  typename boost::detail::function::function_return_type<R>::type
565       result_type;
566 #endif // BOOST_NO_VOID_RETURNS
567
568   private:
569     typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
570               R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
571       vtable_type;
572
573     struct clear_type {};
574
575   public:
576     BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
577
578     // add signature for boost::lambda
579     template<typename Args>
580     struct sig
581     {
582       typedef result_type type;
583     };
584
585 #if BOOST_FUNCTION_NUM_ARGS == 1
586     typedef T0 argument_type;
587 #elif BOOST_FUNCTION_NUM_ARGS == 2
588     typedef T0 first_argument_type;
589     typedef T1 second_argument_type;
590 #endif
591
592     BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
593     BOOST_FUNCTION_ARG_TYPES
594
595     typedef BOOST_FUNCTION_FUNCTION self_type;
596
597     BOOST_FUNCTION_FUNCTION() : function_base() { }
598
599     // MSVC chokes if the following two constructors are collapsed into
600     // one with a default parameter.
601     template<typename Functor>
602     BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
603 #ifndef BOOST_NO_SFINAE
604                             ,typename enable_if_c<
605                             (boost::type_traits::ice_not<
606                              (is_integral<Functor>::value)>::value),
607                                         int>::type = 0
608 #endif // BOOST_NO_SFINAE
609                             ) :
610       function_base()
611     {
612       this->assign_to(f);
613     }
614     template<typename Functor,typename Allocator>
615     BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
616 #ifndef BOOST_NO_SFINAE
617                             ,typename enable_if_c<
618                             (boost::type_traits::ice_not<
619                              (is_integral<Functor>::value)>::value),
620                                         int>::type = 0
621 #endif // BOOST_NO_SFINAE
622                             ) :
623       function_base()
624     {
625       this->assign_to_a(f,a);
626     }
627
628 #ifndef BOOST_NO_SFINAE
629     BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
630 #else
631     BOOST_FUNCTION_FUNCTION(int zero) : function_base()
632     {
633       BOOST_ASSERT(zero == 0);
634     }
635 #endif
636
637     BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
638     {
639       this->assign_to_own(f);
640     }
641
642     ~BOOST_FUNCTION_FUNCTION() { clear(); }
643
644 #if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
645     // MSVC 6.0 and prior require all definitions to be inline, but
646     // these definitions can become very costly.
647     result_type operator()(BOOST_FUNCTION_PARMS) const
648     {
649       if (this->empty())
650         boost::throw_exception(bad_function_call());
651
652       return static_cast<vtable_type*>(vtable)->invoker
653                (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
654     }
655 #else
656     result_type operator()(BOOST_FUNCTION_PARMS) const;
657 #endif
658
659     // The distinction between when to use BOOST_FUNCTION_FUNCTION and
660     // when to use self_type is obnoxious. MSVC cannot handle self_type as
661     // the return type of these assignment operators, but Borland C++ cannot
662     // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
663     // construct.
664     template<typename Functor>
665 #ifndef BOOST_NO_SFINAE
666     typename enable_if_c<
667                (boost::type_traits::ice_not<
668                  (is_integral<Functor>::value)>::value),
669                BOOST_FUNCTION_FUNCTION&>::type
670 #else
671     BOOST_FUNCTION_FUNCTION&
672 #endif
673     operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
674     {
675       this->clear();
676       try {
677         this->assign_to(f);
678       } catch (...) {
679         vtable = 0;
680         throw;
681       }
682       return *this;
683     }
684     template<typename Functor,typename Allocator>
685     void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
686     {
687       this->clear();
688       try {
689         this->assign_to_a(f,a);
690       } catch (...) {
691         vtable = 0;
692         throw;
693       }
694     }
695
696 #ifndef BOOST_NO_SFINAE
697     BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
698     {
699       this->clear();
700       return *this;
701     }
702 #else
703     BOOST_FUNCTION_FUNCTION& operator=(int zero)
704     {
705       BOOST_ASSERT(zero == 0);
706       this->clear();
707       return *this;
708     }
709 #endif
710
711     // Assignment from another BOOST_FUNCTION_FUNCTION
712     BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
713     {
714       if (&f == this)
715         return *this;
716
717       this->clear();
718       try {
719         this->assign_to_own(f);
720       } catch (...) {
721         vtable = 0;
722         throw;
723       }
724       return *this;
725     }
726
727     void swap(BOOST_FUNCTION_FUNCTION& other)
728     {
729       if (&other == this)
730         return;
731
732       BOOST_FUNCTION_FUNCTION tmp = *this;
733       *this = other;
734       other = tmp;
735     }
736
737     // Clear out a target, if there is one
738     void clear()
739     {
740       if (vtable) {
741         static_cast<vtable_type*>(vtable)->clear(this->functor);
742         vtable = 0;
743       }
744     }
745
746 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
747     // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
748     operator bool () const { return !this->empty(); }
749 #else
750   private:
751     struct dummy {
752       void nonnull() {};
753     };
754
755     typedef void (dummy::*safe_bool)();
756
757   public:
758     operator safe_bool () const
759       { return (this->empty())? 0 : &dummy::nonnull; }
760
761     bool operator!() const
762       { return this->empty(); }
763 #endif
764
765   private:
766     void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
767     {
768       if (!f.empty()) {
769         this->vtable = f.vtable;
770         f.vtable->manager(f.functor, this->functor,
771                           boost::detail::function::clone_functor_tag);
772       }
773     }
774
775     template<typename Functor>
776     void assign_to(Functor f)
777     {
778       static vtable_type stored_vtable(f);
779       if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
780       else vtable = 0;
781     }
782     template<typename Functor,typename Allocator>
783     void assign_to_a(Functor f,Allocator a)
784     {
785       static vtable_type stored_vtable(f,a);
786       if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
787       else vtable = 0;
788     }
789   };
790
791   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
792   inline void swap(BOOST_FUNCTION_FUNCTION<
793                      R BOOST_FUNCTION_COMMA
794                      BOOST_FUNCTION_TEMPLATE_ARGS
795                    >& f1,
796                    BOOST_FUNCTION_FUNCTION<
797                      R BOOST_FUNCTION_COMMA
798                      BOOST_FUNCTION_TEMPLATE_ARGS
799                    >& f2)
800   {
801     f1.swap(f2);
802   }
803
804 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
805   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
806   typename BOOST_FUNCTION_FUNCTION<
807       R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type
808    BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
809   ::operator()(BOOST_FUNCTION_PARMS) const
810   {
811     if (this->empty())
812       boost::throw_exception(bad_function_call());
813
814     return static_cast<vtable_type*>(vtable)->invoker
815              (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
816   }
817 #endif
818
819 // Poison comparisons between boost::function objects of the same type.
820 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
821   void operator==(const BOOST_FUNCTION_FUNCTION<
822                           R BOOST_FUNCTION_COMMA
823                           BOOST_FUNCTION_TEMPLATE_ARGS>&,
824                   const BOOST_FUNCTION_FUNCTION<
825                           R BOOST_FUNCTION_COMMA
826                           BOOST_FUNCTION_TEMPLATE_ARGS>&);
827 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
828   void operator!=(const BOOST_FUNCTION_FUNCTION<
829                           R BOOST_FUNCTION_COMMA
830                           BOOST_FUNCTION_TEMPLATE_ARGS>&,
831                   const BOOST_FUNCTION_FUNCTION<
832                           R BOOST_FUNCTION_COMMA
833                           BOOST_FUNCTION_TEMPLATE_ARGS>& );
834
835 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
836
837 #if BOOST_FUNCTION_NUM_ARGS == 0
838 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
839 #else
840 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
841 #endif
842
843 template<typename R BOOST_FUNCTION_COMMA
844          BOOST_FUNCTION_TEMPLATE_PARMS>
845 class function<BOOST_FUNCTION_PARTIAL_SPEC>
846   : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
847 {
848   typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
849   typedef function self_type;
850
851   struct clear_type {};
852
853 public:
854
855   function() : base_type() {}
856
857   template<typename Functor>
858   function(Functor f
859 #ifndef BOOST_NO_SFINAE
860            ,typename enable_if_c<
861                             (boost::type_traits::ice_not<
862                           (is_integral<Functor>::value)>::value),
863                        int>::type = 0
864 #endif
865            ) :
866     base_type(f)
867   {
868   }
869   template<typename Functor,typename Allocator>
870   function(Functor f, Allocator a
871 #ifndef BOOST_NO_SFINAE
872            ,typename enable_if_c<
873                             (boost::type_traits::ice_not<
874                           (is_integral<Functor>::value)>::value),
875                        int>::type = 0
876 #endif
877            ) :
878     base_type(f,a)
879   {
880   }
881
882 #ifndef BOOST_NO_SFINAE
883   function(clear_type*) : base_type() {}
884 #endif
885
886   function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
887
888   function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
889
890   self_type& operator=(const self_type& f)
891   {
892     self_type(f).swap(*this);
893     return *this;
894   }
895
896   template<typename Functor>
897 #ifndef BOOST_NO_SFINAE
898   typename enable_if_c<
899                             (boost::type_traits::ice_not<
900                          (is_integral<Functor>::value)>::value),
901                       self_type&>::type
902 #else
903   self_type&
904 #endif
905   operator=(Functor f)
906   {
907     self_type(f).swap(*this);
908     return *this;
909   }
910
911 #ifndef BOOST_NO_SFINAE
912   self_type& operator=(clear_type*)
913   {
914     this->clear();
915     return *this;
916   }
917 #endif
918
919   self_type& operator=(const base_type& f)
920   {
921     self_type(f).swap(*this);
922     return *this;
923   }
924 };
925
926 #undef BOOST_FUNCTION_PARTIAL_SPEC
927 #endif // have partial specialization
928
929 } // end namespace boost
930
931 // Cleanup after ourselves...
932 #undef BOOST_FUNCTION_VTABLE
933 #undef BOOST_FUNCTION_COMMA
934 #undef BOOST_FUNCTION_FUNCTION
935 #undef BOOST_FUNCTION_FUNCTION_INVOKER
936 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
937 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
938 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
939 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
940 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
941 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
942 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
943 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
944 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
945 #undef BOOST_FUNCTION_TEMPLATE_PARMS
946 #undef BOOST_FUNCTION_TEMPLATE_ARGS
947 #undef BOOST_FUNCTION_PARMS
948 #undef BOOST_FUNCTION_PARM
949 #undef BOOST_FUNCTION_ARGS
950 #undef BOOST_FUNCTION_ARG_TYPE
951 #undef BOOST_FUNCTION_ARG_TYPES
952 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
953 #undef BOOST_FUNCTION_RETURN
954
955 #if defined(BOOST_MSVC)
956 #   pragma warning( pop )
957 #endif