]> git.lyx.org Git - lyx.git/blob - boost/boost/function/function_template.hpp
update boost to pre-1.30.0
[lyx.git] / boost / boost / function / function_template.hpp
1 // Boost.Function library
2
3 // Copyright (C) 2001-2003 Doug Gregor (gregod@cs.rpi.edu)
4 //
5 // Permission to copy, use, sell and distribute this software is granted
6 // provided this copyright notice appears in all copies.
7 // Permission to modify the code and to distribute modified code is granted
8 // provided this copyright notice appears in all copies, and a notice
9 // that the code was modified is included with the copyright notice.
10 //
11 // This software is provided "as is" without express or implied warranty,
12 // and with no claim as to its suitability for any purpose.
13
14 // For more information, see http://www.boost.org
15
16 // Note: this header is a header template and must NOT have multiple-inclusion
17 // protection.
18 #include <boost/function/detail/prologue.hpp>
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(arg, BOOST_PP_CAT(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 // Type of the default allocator
36 #ifndef BOOST_NO_STD_ALLOCATOR
37 #  define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
38 #else
39 #  define BOOST_FUNCTION_DEFAULT_ALLOCATOR int
40 #endif // BOOST_NO_STD_ALLOCATOR
41
42 // Comma if nonzero number of arguments
43 #if BOOST_FUNCTION_NUM_ARGS == 0
44 #  define BOOST_FUNCTION_COMMA
45 #else
46 #  define BOOST_FUNCTION_COMMA ,
47 #endif // BOOST_FUNCTION_NUM_ARGS > 0
48
49 // Class names used in this version of the code
50 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
51 #define BOOST_FUNCTION_FUNCTION_INVOKER \
52   BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
53 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
54   BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
55 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
56   BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
57 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
58   BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
59 #define BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER \
60   BOOST_JOIN(stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
61 #define BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER \
62   BOOST_JOIN(stateless_void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
63 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
64   BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
65 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
66   BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
67 #define BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER \
68   BOOST_JOIN(get_stateless_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
69
70 namespace boost {
71   namespace detail {
72     namespace function {
73       template<
74         typename FunctionPtr,
75         typename R BOOST_FUNCTION_COMMA
76         BOOST_FUNCTION_TEMPLATE_PARMS
77         >
78       struct BOOST_FUNCTION_FUNCTION_INVOKER
79       {
80         static R invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
81                         BOOST_FUNCTION_PARMS)
82         {
83           FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
84           return f(BOOST_FUNCTION_ARGS);
85         }
86       };
87
88       template<
89         typename FunctionPtr,
90         typename R BOOST_FUNCTION_COMMA
91         BOOST_FUNCTION_TEMPLATE_PARMS
92         >
93       struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
94       {
95         static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA
96                                BOOST_FUNCTION_PARMS)
97
98         {
99           FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
100           f(BOOST_FUNCTION_ARGS);
101           return unusable();
102         }
103       };
104
105       template<
106         typename FunctionObj,
107         typename R BOOST_FUNCTION_COMMA
108         BOOST_FUNCTION_TEMPLATE_PARMS
109       >
110       struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
111       {
112         static R invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA
113                         BOOST_FUNCTION_PARMS)
114
115         {
116           FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
117           return (*f)(BOOST_FUNCTION_ARGS);
118         }
119       };
120
121       template<
122         typename FunctionObj,
123         typename R BOOST_FUNCTION_COMMA
124         BOOST_FUNCTION_TEMPLATE_PARMS
125       >
126       struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
127       {
128         static unusable invoke(any_pointer function_obj_ptr
129                                BOOST_FUNCTION_COMMA
130                                BOOST_FUNCTION_PARMS)
131
132         {
133           FunctionObj* f = (FunctionObj*)(function_obj_ptr.obj_ptr);
134           (*f)(BOOST_FUNCTION_ARGS);
135           return unusable();
136         }
137       };
138
139       template<
140         typename FunctionObj,
141         typename R BOOST_FUNCTION_COMMA
142         BOOST_FUNCTION_TEMPLATE_PARMS
143       >
144       struct BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
145       {
146         static R invoke(any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS)
147         {
148           FunctionObj f = FunctionObj();
149           return f(BOOST_FUNCTION_ARGS);
150         }
151       };
152
153       template<
154         typename FunctionObj,
155         typename R BOOST_FUNCTION_COMMA
156         BOOST_FUNCTION_TEMPLATE_PARMS
157       >
158       struct BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
159       {
160         static unusable invoke(any_pointer BOOST_FUNCTION_COMMA
161                                BOOST_FUNCTION_PARMS)
162
163         {
164           FunctionObj f = FunctionObj();
165           f(BOOST_FUNCTION_ARGS);
166           return unusable();
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     typedef typename detail::function::function_return_type<R>::type
244       internal_result_type;
245
246     struct clear_type {};
247
248   public:
249     BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
250
251     // add signature for boost::lambda
252     template<typename Args>
253     struct sig
254     {
255       typedef internal_result_type type;
256     };
257
258 #if BOOST_FUNCTION_NUM_ARGS == 1
259     typedef T0 argument_type;
260 #elif BOOST_FUNCTION_NUM_ARGS == 2
261     typedef T0 first_argument_type;
262     typedef T1 second_argument_type;
263 #endif
264
265     BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
266     BOOST_FUNCTION_ARG_TYPES
267
268 #ifndef BOOST_NO_VOID_RETURNS
269     typedef R         result_type;
270 #else
271     typedef internal_result_type result_type;
272 #endif // BOOST_NO_VOID_RETURNS
273     typedef Allocator allocator_type;
274     typedef BOOST_FUNCTION_FUNCTION self_type;
275
276     BOOST_FUNCTION_FUNCTION() : function_base()
277                               , invoker(0) {}
278
279     // MSVC chokes if the following two constructors are collapsed into
280     // one with a default parameter.
281     template<typename Functor>
282     BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
283 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
284                             ,typename detail::function::enable_if<
285                             (::boost::type_traits::ice_not<
286                              (is_same<Functor, int>::value)>::value),
287                                         int>::type = 0
288 #endif // BOOST_FUNCTION_NO_ENABLE_IF
289                             ) :
290       function_base(),
291       invoker(0)
292     {
293       this->assign_to(f);
294     }
295
296 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
297     BOOST_FUNCTION_FUNCTION(clear_type*) : function_base(), invoker(0) {}
298 #else
299     BOOST_FUNCTION_FUNCTION(int zero) : function_base(), invoker(0)
300     {
301       BOOST_ASSERT(zero == 0);
302     }
303 #endif
304
305     BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) :
306       function_base(),
307       invoker(0)
308     {
309       this->assign_to_own(f);
310     }
311
312     ~BOOST_FUNCTION_FUNCTION() { clear(); }
313
314     result_type operator()(BOOST_FUNCTION_PARMS) const
315     {
316       if (this->empty())
317         boost::throw_exception(bad_function_call());
318
319       internal_result_type result = invoker(function_base::functor
320                                             BOOST_FUNCTION_COMMA
321                                             BOOST_FUNCTION_ARGS);
322
323 #ifndef BOOST_NO_VOID_RETURNS
324       return static_cast<result_type>(result);
325 #else
326       return result;
327 #endif // BOOST_NO_VOID_RETURNS
328     }
329
330     // The distinction between when to use BOOST_FUNCTION_FUNCTION and
331     // when to use self_type is obnoxious. MSVC cannot handle self_type as
332     // the return type of these assignment operators, but Borland C++ cannot
333     // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
334     // construct.
335     template<typename Functor>
336 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
337     typename detail::function::enable_if<
338                (::boost::type_traits::ice_not<
339                  (is_same<Functor, int>::value)>::value),
340                BOOST_FUNCTION_FUNCTION&>::type
341 #else
342     BOOST_FUNCTION_FUNCTION&
343 #endif
344     operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
345     {
346       self_type(f).swap(*this);
347       return *this;
348     }
349
350 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
351     BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
352     {
353       this->clear();
354       return *this;
355     }
356 #else
357     BOOST_FUNCTION_FUNCTION& operator=(int zero)
358     {
359       BOOST_ASSERT(zero == 0);
360       this->clear();
361       return *this;
362     }
363 #endif
364
365     // Assignment from another BOOST_FUNCTION_FUNCTION
366     BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
367     {
368       if (&f == this)
369         return *this;
370
371       self_type(f).swap(*this);
372       return *this;
373     }
374
375     void swap(BOOST_FUNCTION_FUNCTION& other)
376     {
377       if (&other == this)
378         return;
379
380       std::swap(function_base::manager, other.manager);
381       std::swap(function_base::functor, other.functor);
382       std::swap(invoker, other.invoker);
383     }
384
385     // Clear out a target, if there is one
386     void clear()
387     {
388       if (function_base::manager) {
389         function_base::functor =
390           function_base::manager(function_base::functor,
391                                  detail::function::destroy_functor_tag);
392       }
393
394       function_base::manager = 0;
395       invoker = 0;
396     }
397
398 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
399     // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
400     operator bool () const { return !this->empty(); }
401 #else
402   private:
403     struct dummy {
404       void nonnull() {};
405     };
406
407     typedef void (dummy::*safe_bool)();
408
409   public:
410     operator safe_bool () const
411       { return (this->empty())? 0 : &dummy::nonnull; }
412
413     bool operator!() const
414       { return this->empty(); }
415 #endif
416
417   private:
418     void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
419     {
420       if (!f.empty()) {
421         invoker = f.invoker;
422         function_base::manager = f.manager;
423         function_base::functor =
424           f.manager(f.functor, detail::function::clone_functor_tag);
425       }
426     }
427
428     template<typename Functor>
429     void assign_to(Functor f)
430     {
431       typedef typename detail::function::get_function_tag<Functor>::type tag;
432       this->assign_to(f, tag());
433     }
434
435     template<typename FunctionPtr>
436     void assign_to(FunctionPtr f, detail::function::function_ptr_tag)
437     {
438       clear();
439
440       if (f) {
441         typedef typename detail::function::BOOST_FUNCTION_GET_FUNCTION_INVOKER<
442                            FunctionPtr,
443                            R BOOST_FUNCTION_COMMA
444                            BOOST_FUNCTION_TEMPLATE_ARGS
445                          >::type
446           invoker_type;
447
448         invoker = &invoker_type::invoke;
449         function_base::manager =
450           &detail::function::functor_manager<FunctionPtr, Allocator>::manage;
451         function_base::functor =
452           function_base::manager(detail::function::make_any_pointer(
453                             // should be a reinterpret cast, but some compilers
454                             // insist on giving cv-qualifiers to free functions
455                             (void (*)())(f)
456                           ),
457                           detail::function::clone_functor_tag);
458       }
459     }
460
461 #if BOOST_FUNCTION_NUM_ARGS > 0
462     template<typename MemberPtr>
463     void assign_to(MemberPtr f, detail::function::member_ptr_tag)
464     {
465       this->assign_to(mem_fn(f));
466     }
467 #endif // BOOST_FUNCTION_NUM_ARGS > 0
468
469     template<typename FunctionObj>
470     void assign_to(FunctionObj f, detail::function::function_obj_tag)
471     {
472       if (!detail::function::has_empty_target(addressof(f))) {
473         typedef
474           typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
475                                        FunctionObj,
476                                        R BOOST_FUNCTION_COMMA
477                                        BOOST_FUNCTION_TEMPLATE_ARGS
478                                      >::type
479           invoker_type;
480
481         invoker = &invoker_type::invoke;
482         function_base::manager = &detail::function::functor_manager<
483                                     FunctionObj, Allocator>::manage;
484 #ifndef BOOST_NO_STD_ALLOCATOR
485         typedef typename Allocator::template rebind<FunctionObj>::other
486           allocator_type;
487         typedef typename allocator_type::pointer pointer_type;
488         allocator_type allocator;
489         pointer_type copy = allocator.allocate(1);
490         allocator.construct(copy, f);
491
492         // Get back to the original pointer type
493         FunctionObj* new_f = static_cast<FunctionObj*>(copy);
494 #else
495         FunctionObj* new_f = new FunctionObj(f);
496 #endif // BOOST_NO_STD_ALLOCATOR
497         function_base::functor =
498           detail::function::make_any_pointer(static_cast<void*>(new_f));
499       }
500     }
501
502     template<typename FunctionObj>
503     void assign_to(const reference_wrapper<FunctionObj>& f,
504                    detail::function::function_obj_ref_tag)
505     {
506       if (!detail::function::has_empty_target(f.get_pointer())) {
507         typedef
508           typename detail::function::BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
509                                        FunctionObj,
510                                        R BOOST_FUNCTION_COMMA
511                                        BOOST_FUNCTION_TEMPLATE_ARGS
512                                      >::type
513           invoker_type;
514
515         invoker = &invoker_type::invoke;
516         function_base::manager = &detail::function::trivial_manager;
517         function_base::functor =
518           function_base::manager(
519             detail::function::make_any_pointer(
520               const_cast<FunctionObj*>(f.get_pointer())),
521             detail::function::clone_functor_tag);
522       }
523     }
524
525     template<typename FunctionObj>
526     void assign_to(FunctionObj, detail::function::stateless_function_obj_tag)
527     {
528       typedef
529           typename detail::function::
530                      BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER<
531                        FunctionObj,
532                        R BOOST_FUNCTION_COMMA
533                        BOOST_FUNCTION_TEMPLATE_ARGS
534                      >::type
535           invoker_type;
536       invoker = &invoker_type::invoke;
537       function_base::manager = &detail::function::trivial_manager;
538       function_base::functor = detail::function::make_any_pointer(this);
539     }
540
541     typedef internal_result_type (*invoker_type)(detail::function::any_pointer
542                                                  BOOST_FUNCTION_COMMA
543                                                  BOOST_FUNCTION_TEMPLATE_ARGS);
544
545     invoker_type invoker;
546   };
547
548   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
549            typename Allocator>
550   inline void swap(BOOST_FUNCTION_FUNCTION<
551                      R BOOST_FUNCTION_COMMA
552                      BOOST_FUNCTION_TEMPLATE_ARGS ,
553                      Allocator
554                    >& f1,
555                    BOOST_FUNCTION_FUNCTION<
556                      R BOOST_FUNCTION_COMMA
557                      BOOST_FUNCTION_TEMPLATE_ARGS,
558                      Allocator
559                    >& f2)
560   {
561     f1.swap(f2);
562   }
563
564 #if !defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)                         \
565  && !defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG)                              \
566  && (BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
567
568 #if BOOST_FUNCTION_NUM_ARGS == 0
569 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
570 #else
571 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
572 #endif
573
574 template<typename R BOOST_FUNCTION_COMMA
575          BOOST_FUNCTION_TEMPLATE_PARMS,
576          typename Allocator>
577 class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
578   : public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
579                                    BOOST_FUNCTION_COMMA Allocator>
580 {
581   typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
582                                   BOOST_FUNCTION_COMMA Allocator> base_type;
583   typedef function self_type;
584
585   struct clear_type {};
586
587 public:
588   typedef typename base_type::allocator_type allocator_type;
589
590   function() : base_type() {}
591
592   template<typename Functor>
593   function(Functor f
594 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
595            ,typename detail::function::enable_if<
596                             (::boost::type_traits::ice_not<
597                           (is_same<Functor, int>::value)>::value),
598                        int>::type = 0
599 #endif
600            ) :
601     base_type(f)
602   {
603   }
604
605 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
606   function(clear_type*) : base_type() {}
607 #endif
608
609   function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
610
611   function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
612
613   self_type& operator=(const self_type& f)
614   {
615     self_type(f).swap(*this);
616     return *this;
617   }
618
619   template<typename Functor>
620 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
621   typename detail::function::enable_if<
622                             (::boost::type_traits::ice_not<
623                          (is_same<Functor, int>::value)>::value),
624                       self_type&>::type
625 #else
626   self_type&
627 #endif
628   operator=(Functor f)
629   {
630     self_type(f).swap(*this);
631     return *this;
632   }
633
634 #ifndef BOOST_FUNCTION_NO_ENABLE_IF
635   self_type& operator=(clear_type*)
636   {
637     this->clear();
638     return *this;
639   }
640 #endif
641
642   self_type& operator=(const base_type& f)
643   {
644     self_type(f).swap(*this);
645     return *this;
646   }
647 };
648
649 #undef BOOST_FUNCTION_PARTIAL_SPEC
650 #endif // have partial specialization
651
652 } // end namespace boost
653
654 // Cleanup after ourselves...
655 #undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
656 #undef BOOST_FUNCTION_COMMA
657 #undef BOOST_FUNCTION_FUNCTION
658 #undef BOOST_FUNCTION_FUNCTION_INVOKER
659 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
660 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
661 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
662 #undef BOOST_FUNCTION_STATELESS_FUNCTION_OBJ_INVOKER
663 #undef BOOST_FUNCTION_STATELESS_VOID_FUNCTION_OBJ_INVOKER
664 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
665 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
666 #undef BOOST_FUNCTION_GET_STATELESS_FUNCTION_OBJ_INVOKER
667 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
668 #undef BOOST_FUNCTION_TEMPLATE_PARMS
669 #undef BOOST_FUNCTION_TEMPLATE_ARGS
670 #undef BOOST_FUNCTION_PARMS
671 #undef BOOST_FUNCTION_PARM
672 #undef BOOST_FUNCTION_ARGS
673 #undef BOOST_FUNCTION_ARG_TYPE
674 #undef BOOST_FUNCTION_ARG_TYPES