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