Ugly, not-to-be-pushed sucking in of all of Boost to get windows to work.
[dyninst.git] / external / boost / function / function_template.hpp
1 // Boost.Function library
2
3 //  Copyright Douglas Gregor 2001-2003. 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(arg, BOOST_PP_CAT(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_STATELESS_FUNCTION_OBJ_INVOKER \
54   BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
55 #define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \
56   BOOST_JOIN(stateless_void_function_obj_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_STATELESS_FUNCTION_OBJ_INVOKER \
62   BOOST_JOIN(get_stateless_function_obj_invoker,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(any_pointer 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(any_pointer 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(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
115                         BOOST_FUNCTION_PARMS)
116
117         {
118           FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
119           return (*f)(BOOST_FUNCTION_ARGS);
120         }
121       };
122
123       template<
124         typename FunctionObj,
125         typename R BOOST_FUNCTION_COMMA
126         BOOST_FUNCTION_TEMPLATE_PARMS
127       >
128       struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
129       {
130         static BOOST_FUNCTION_VOID_RETURN_TYPE
131         invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
132                BOOST_FUNCTION_PARMS)
133
134         {
135           FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
136           BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
137         }
138       };
139
140       template<
141         typename FunctionObj,
142         typename R BOOST_FUNCTION_COMMA
143         BOOST_FUNCTION_TEMPLATE_PARMS
144       >
145       struct BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
146       {
147         static R invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
148         {
149           FunctionObj f = FunctionObj();
150           return f(BOOST_FUNCTION_ARGS);
151         }
152       };
153
154       template<
155         typename FunctionObj,
156         typename R BOOST_FUNCTION_COMMA
157         BOOST_FUNCTION_TEMPLATE_PARMS
158       >
159       struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
160       {
161         static BOOST_FUNCTION_VOID_RETURN_TYPE
162         invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
163
164         {
165           FunctionObj f = FunctionObj();
166           BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
167         }
168       };
169
170       template<
171         typename FunctionPtr,
172         typename R BOOST_FUNCTION_COMMA
173         BOOST_FUNCTION_TEMPLATE_PARMS
174       >
175       struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
176       {
177         typedef typename ct_if<(is_void<R>::value),
178                             BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
179                             FunctionPtr,
180                             R BOOST_FUNCTION_COMMA
181                             BOOST_FUNCTION_TEMPLATE_ARGS
182                           >,
183                           BOOST_FUNCTION_FUNCTION_INVOKER<
184                             FunctionPtr,
185                             R BOOST_FUNCTION_COMMA
186                             BOOST_FUNCTION_TEMPLATE_ARGS
187                           >
188                        >::type type;
189       };
190
191       template<
192         typename FunctionObj,
193         typename R BOOST_FUNCTION_COMMA
194         BOOST_FUNCTION_TEMPLATE_PARMS
195        >
196       struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
197       {
198         typedef typename ct_if<(is_void<R>::value),
199                             BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
200                             FunctionObj,
201                             R BOOST_FUNCTION_COMMA
202                             BOOST_FUNCTION_TEMPLATE_ARGS
203                           >,
204                           BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
205                             FunctionObj,
206                             R BOOST_FUNCTION_COMMA
207                             BOOST_FUNCTION_TEMPLATE_ARGS
208                           >
209                        >::type type;
210       };
211
212       template<
213         typename FunctionObj,
214         typename R BOOST_FUNCTION_COMMA
215         BOOST_FUNCTION_TEMPLATE_PARMS
216        >
217       struct BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
218       {
219         typedef typename ct_if<(is_void<R>::value),
220                             BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER<
221                             FunctionObj,
222                             R BOOST_FUNCTION_COMMA
223                             BOOST_FUNCTION_TEMPLATE_ARGS
224                           >,
225                           BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER<
226                             FunctionObj,
227                             R BOOST_FUNCTION_COMMA
228                             BOOST_FUNCTION_TEMPLATE_ARGS
229                           >
230                        >::type type;
231       };
232
233     } // end namespace function
234   } // end namespace detail
235
236   template<
237     typename R BOOST_FUNCTION_COMMA
238     BOOST_FUNCTION_TEMPLATE_PARMS,
239     typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
240   >
241   class BOOST_FUNCTION_FUNCTION : public function_base
242   {
243   public:
244 #ifndef BOOST_NO_VOID_RETURNS
245     typedef R         result_type;
246 #else
247     typedef  typename detail::function::function_return_type<R>::type
248       result_type;
249 #endif // BOOST_NO_VOID_RETURNS
250
251   private:
252     struct clear_type {};
253
254   public:
255     BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
256
257     // add signature for boost::lambda
258     template<typename Args>
259     struct sig
260     {
261       typedef result_type type;
262     };
263
264 #if BOOST_FUNCTION_NUM_ARGS == 1
265     typedef T0 argument_type;
266 #elif BOOST_FUNCTION_NUM_ARGS == 2
267     typedef T0 first_argument_type;
268     typedef T1 second_argument_type;
269 #endif
270
271     BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
272     BOOST_FUNCTION_ARG_TYPES
273
274     typedef Allocator allocator_type;
275     typedef BOOST_FUNCTION_FUNCTION self_type;
276
277     BOOST_FUNCTION_FUNCTION() : function_base()
278                               , invoker(0) {}
279
280     // MSVC chokes if the following two constructors are collapsed into
281     // one with a default parameter.
282     template<typename Functor>
283     BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
284 #ifndef BOOST_NO_SFINAE
285                             ,typename enable_if_c<
286                             (::boost::type_traits::ice_not<
287                              (is_integral<Functor>::value)>::value),
288                                         int>::type = 0
289 #endif // BOOST_NO_SFINAE
290                             ) :
291       function_base(),
292       invoker(0)
293     {
294       this->assign_to(f);
295     }
296
297 #ifndef BOOST_NO_SFINAE
298     BOOST_FUNCTION_FUNCTION(clear_type*) : function_base(), invoker(0) {}
299 #else
300     BOOST_FUNCTION_FUNCTION(int zero) : function_base(), invoker(0)
301     {
302       BOOST_ASSERT(zero == 0);
303     }
304 #endif
305
306     BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
307       function_base(),
308       invoker(0)
309     {
310       this->assign_to_own(f);
311     }
312
313     ~BOOST_FUNCTION_FUNCTION() { clear(); }
314
315 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
316     // MSVC 6.0 and prior require all definitions to be inline, but
317     // these definitions can become very costly.
318     result_type operator()(BOOST_FUNCTION_PARMS) const
319     {
320       if (this->empty())
321         boost::throw_exception(bad_function_call());
322
323       return invoker(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
324     }
325 #else
326     result_type operator()(BOOST_FUNCTION_PARMS) const;
327 #endif
328
329     // The distinction between when to use BOOST_FUNCTION_FUNCTION and
330     // when to use self_type is obnoxious. MSVC cannot handle self_type as
331     // the return type of these assignment operators, but Borland C++ cannot
332     // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
333     // construct.
334     template<typename Functor>
335 #ifndef BOOST_NO_SFINAE
336     typename enable_if_c<
337                (::boost::type_traits::ice_not<
338                  (is_integral<Functor>::value)>::value),
339                BOOST_FUNCTION_FUNCTION&>::type
340 #else
341     BOOST_FUNCTION_FUNCTION&
342 #endif
343     operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
344     {
345       self_type(f).swap(*this);
346       return *this;
347     }
348
349 #ifndef BOOST_NO_SFINAE
350     BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
351     {
352       this->clear();
353       return *this;
354     }
355 #else
356     BOOST_FUNCTION_FUNCTION& operator=(int zero)
357     {
358       BOOST_ASSERT(zero == 0);
359       this->clear();
360       return *this;
361     }
362 #endif
363
364     // Assignment from another BOOST_FUNCTION_FUNCTION
365     BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
366     {
367       if (&f == this)
368         return *this;
369
370       self_type(f).swap(*this);
371       return *this;
372     }
373
374     void swap(BOOST_FUNCTION_FUNCTION& other)
375     {
376       if (&other == this)
377         return;
378
379       std::swap(this->manager, other.manager);
380       std::swap(this->functor, other.functor);
381       std::swap(invoker, other.invoker);
382     }
383
384     // Clear out a target, if there is one
385     void clear()
386     {
387       if (this->manager) {
388         function_base::functor =
389           this->manager(this->functor, detail::function::destroy_functor_tag);
390       }
391
392       this->manager = 0;
393       invoker = 0;
394     }
395
396 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
397     // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
398     operator bool () const { return !this->empty(); }
399 #else
400   private:
401     struct dummy {
402       void nonnull() {};
403     };
404
405     typedef void (dummy::*safe_bool)();
406
407   public:
408     operator safe_bool () const
409       { return (this->empty())? 0 : &dummy::nonnull; }
410
411     bool operator!() const
412       { return this->empty(); }
413 #endif
414
415   private:
416     void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
417     {
418       if (!f.empty()) {
419         invoker = f.invoker;
420         this->manager = f.manager;
421         this->functor =
422           f.manager(f.functor, detail::function::clone_functor_tag);
423       }
424     }
425
426     template<typename Functor>
427     void assign_to(Functor f)
428     {
429       typedef typename detail::function::get_function_tag<Functor>::type tag;
430       this->assign_to(f, tag());
431     }
432
433     template<typename FunctionPtr>
434     void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
435     {
436       clear();
437
438       if (f) {
439         typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
440                            FunctionPtr,
441                            R BOOST_FUNCTION_COMMA
442                            BOOST_FUNCTION_TEMPLATE_ARGS
443                          >::type
444           actual_invoker_type;
445
446         invoker = &actual_invoker_type::invoke;
447         this->manager =
448           &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
449         this->functor =
450           this->manager(detail::function::make_any_pointer(
451                             // should be a reinterpret cast, but some compilers
452                             // insist on giving cv-qualifiers to free functions
453                             (void (*)())(f)
454                           ),
455                           detail::function::clone_functor_tag);
456       }
457     }
458
459 #if BOOST_FUNCTION_NUM_ARGS > 0
460     template<typename MemberPtr>
461     void assign_to(MemberPtr f, detail::function::member_ptr_tag)
462     {
463       this->assign_to(mem_fn(f));
464     }
465 #endif // BOOST_FUNCTION_NUM_ARGS > 0
466
467     template<typename FunctionObj>
468     void assign_to(FunctionObj f, detail::function::function_obj_tag)
469     {
470       if (!detail::function::has_empty_target(boost::addressof(f))) {
471         typedef
472           typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
473                                        FunctionObj,
474                                        R BOOST_FUNCTION_COMMA
475                                        BOOST_FUNCTION_TEMPLATE_ARGS
476                                      >::type
477           actual_invoker_type;
478
479         invoker = &actual_invoker_type::invoke;
480         this->manager = &detail::function::functor_manager<
481                                     FunctionObj, Allocator>::manage;
482 #ifndef BOOST_NO_STD_ALLOCATOR
483         typedef typename Allocator::template rebind<FunctionObj>::other
484           rebound_allocator_type;
485         typedef typename rebound_allocator_type::pointer pointer_type;
486         rebound_allocator_type allocator;
487         pointer_type copy = allocator.allocate(1);
488         allocator.construct(copy, f);
489
490         // Get back to the original pointer type
491         FunctionObj* new_f = static_cast<FunctionObj*>(copy);
492 #else
493         FunctionObj* new_f = new FunctionObj(f);
494 #endif // BOOST_NO_STD_ALLOCATOR
495         this->functor =
496           detail::function::make_any_pointer(static_cast<void*>(new_f));
497       }
498     }
499
500     template<typename FunctionObj>
501     void assign_to(const reference_wrapper<FunctionObj>& f,
502                    detail::function::function_obj_ref_tag)
503     {
504       if (!detail::function::has_empty_target(f.get_pointer())) {
505         typedef
506           typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
507                                        FunctionObj,
508                                        R BOOST_FUNCTION_COMMA
509                                        BOOST_FUNCTION_TEMPLATE_ARGS
510                                      >::type
511           actual_invoker_type;
512
513         invoker = &actual_invoker_type::invoke;
514         this->manager = &detail::function::trivial_manager<FunctionObj>::get;
515         this->functor =
516           this->manager(
517             detail::function::make_any_pointer(
518               const_cast<FunctionObj*>(f.get_pointer())),
519             detail::function::clone_functor_tag);
520       }
521     }
522
523     template<typename FunctionObj>
524     void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
525     {
526       typedef
527           typename detail::function::
528                      BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
529                        FunctionObj,
530                        R BOOST_FUNCTION_COMMA
531                        BOOST_FUNCTION_TEMPLATE_ARGS
532                      >::type
533           actual_invoker_type;
534       invoker = &actual_invoker_type::invoke;
535       this->manager = &detail::function::trivial_manager<FunctionObj>::get;
536       this->functor = detail::function::make_any_pointer(this);
537     }
538
539     typedef result_type (*invoker_type)(detail::function::any_pointer
540                                         BOOST_FUNCTION_COMMA
541                                         BOOST_FUNCTION_TEMPLATE_ARGS);
542
543     invoker_type invoker;
544   };
545
546   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
547            typename Allocator>
548   inline void swap(BOOST_FUNCTION_FUNCTION<
549                      R BOOST_FUNCTION_COMMA
550                      BOOST_FUNCTION_TEMPLATE_ARGS ,
551                      Allocator
552                    >& f1,
553                    BOOST_FUNCTION_FUNCTION<
554                      R BOOST_FUNCTION_COMMA
555                      BOOST_FUNCTION_TEMPLATE_ARGS,
556                      Allocator
557                    >& f2)
558   {
559     f1.swap(f2);
560   }
561
562 #if !BOOST_WORKAROUND(BOOST_MSVC, <= 1200)
563   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
564            typename Allocator>
565   typename BOOST_FUNCTION_FUNCTION<
566       R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, 
567       Allocator>::result_type
568    BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
569
570                            Allocator>
571   ::operator()(BOOST_FUNCTION_PARMS) const
572   {
573     if (this->empty())
574       boost::throw_exception(bad_function_call());
575     
576     return invoker(this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
577   }
578 #endif
579
580 // Poison comparisons between boost::function objects of the same type.
581 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
582          typename Allocator>
583   void operator==(const BOOST_FUNCTION_FUNCTION<
584                           R BOOST_FUNCTION_COMMA
585                           BOOST_FUNCTION_TEMPLATE_ARGS ,
586                           Allocator>&,
587                   const BOOST_FUNCTION_FUNCTION<
588                           R BOOST_FUNCTION_COMMA
589                           BOOST_FUNCTION_TEMPLATE_ARGS ,
590                   Allocator>&);
591 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
592          typename Allocator>
593   void operator!=(const BOOST_FUNCTION_FUNCTION<
594                           R BOOST_FUNCTION_COMMA
595                           BOOST_FUNCTION_TEMPLATE_ARGS ,
596                           Allocator>&,
597                   const BOOST_FUNCTION_FUNCTION<
598                           R BOOST_FUNCTION_COMMA
599                           BOOST_FUNCTION_TEMPLATE_ARGS ,
600                   Allocator>&);
601
602 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
603
604 #if BOOST_FUNCTION_NUM_ARGS == 0
605 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
606 #else
607 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
608 #endif
609
610 template<typename R BOOST_FUNCTION_COMMA
611          BOOST_FUNCTION_TEMPLATE_PARMS,
612          typename Allocator>
613 class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
614   : public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
615                                    BOOST_FUNCTION_COMMA Allocator>
616 {
617   typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
618                                   BOOST_FUNCTION_COMMA Allocator> base_type;
619   typedef function self_type;
620
621   struct clear_type {};
622
623 public:
624   typedef typename base_type::allocator_type allocator_type;
625
626   function() : base_type() {}
627
628   template<typename Functor>
629   function(Functor f
630 #ifndef BOOST_NO_SFINAE
631            ,typename enable_if_c<
632                             (::boost::type_traits::ice_not<
633                           (is_integral<Functor>::value)>::value),
634                        int>::type = 0
635 #endif
636            ) :
637     base_type(f)
638   {
639   }
640
641 #ifndef BOOST_NO_SFINAE
642   function(clear_type*) : base_type() {}
643 #endif
644
645   function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
646
647   function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
648
649   self_type& operator=(const self_type& f)
650   {
651     self_type(f).swap(*this);
652     return *this;
653   }
654
655   template<typename Functor>
656 #ifndef BOOST_NO_SFINAE
657   typename enable_if_c<
658                             (::boost::type_traits::ice_not<
659                          (is_integral<Functor>::value)>::value),
660                       self_type&>::type
661 #else
662   self_type&
663 #endif
664   operator=(Functor f)
665   {
666     self_type(f).swap(*this);
667     return *this;
668   }
669
670 #ifndef BOOST_NO_SFINAE
671   self_type& operator=(clear_type*)
672   {
673     this->clear();
674     return *this;
675   }
676 #endif
677
678   self_type& operator=(const base_type& f)
679   {
680     self_type(f).swap(*this);
681     return *this;
682   }
683 };
684
685 #undef BOOST_FUNCTION_PARTIAL_SPEC
686 #endif // have partial specialization
687
688 } // end namespace boost
689
690 // Cleanup after ourselves...
691 #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
692 #undef BOOST_FUNCTION_COMMA
693 #undef BOOST_FUNCTION_FUNCTION
694 #undef BOOST_FUNCTION_FUNCTION_INVOKER
695 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
696 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
697 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
698 #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
699 #undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
700 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
701 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
702 #undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
703 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
704 #undef BOOST_FUNCTION_TEMPLATE_PARMS
705 #undef BOOST_FUNCTION_TEMPLATE_ARGS
706 #undef BOOST_FUNCTION_PARMS
707 #undef BOOST_FUNCTION_PARM
708 #undef BOOST_FUNCTION_ARGS
709 #undef BOOST_FUNCTION_ARG_TYPE
710 #undef BOOST_FUNCTION_ARG_TYPES
711 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
712 #undef BOOST_FUNCTION_RETURN