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