1 // Boost.Function library
2 
3 //  Copyright Douglas Gregor 2001-2006
4 //  Copyright Emil Dotchevski 2007
5 //  Use, modification and distribution is subject to the Boost Software License, Version 1.0.
6 //  (See accompanying file LICENSE_1_0.txt or copy at
7 //  http://www.boost.org/LICENSE_1_0.txt)
8 
9 // For more information, see http://www.boost.org
10 
11 // Note: this header is a header template and must NOT have multiple-inclusion
12 // protection.
13 #include <boost/function/detail/prologue.hpp>
14 #include <boost/core/no_exceptions_support.hpp>
15 
16 #if defined(BOOST_MSVC)
17 #   pragma warning( push )
18 #   pragma warning( disable : 4127 ) // "conditional expression is constant"
19 #endif
20 
21 #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
22 
23 #define BOOST_FUNCTION_TEMPLATE_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, T)
24 
25 #define BOOST_FUNCTION_PARM(J,I,D) BOOST_PP_CAT(T,I) BOOST_PP_CAT(a,I)
26 
27 #define BOOST_FUNCTION_PARMS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_PARM,BOOST_PP_EMPTY)
28 
29 #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES
30 #   define BOOST_FUNCTION_ARGS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, a)
31 #else
32 #   define BOOST_FUNCTION_ARG(J,I,D) static_cast<BOOST_PP_CAT(T,I)&&>(BOOST_PP_CAT(a,I))
33 #   define BOOST_FUNCTION_ARGS BOOST_PP_ENUM(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG,BOOST_PP_EMPTY)
34 #endif
35 
36 #define BOOST_FUNCTION_ARG_TYPE(J,I,D) \
37   typedef BOOST_PP_CAT(T,I) BOOST_PP_CAT(BOOST_PP_CAT(arg, BOOST_PP_INC(I)),_type);
38 
39 #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
40 
41 // Comma if nonzero number of arguments
42 #if BOOST_FUNCTION_NUM_ARGS == 0
43 #  define BOOST_FUNCTION_COMMA
44 #else
45 #  define BOOST_FUNCTION_COMMA ,
46 #endif // BOOST_FUNCTION_NUM_ARGS > 0
47 
48 // Class names used in this version of the code
49 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
50 #define BOOST_FUNCTION_FUNCTION_INVOKER \
51   BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
52 #define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
53   BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
54 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
55   BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
56 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
57   BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
58 #define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
59   BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
60 #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
61   BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
62 #define BOOST_FUNCTION_MEMBER_INVOKER \
63   BOOST_JOIN(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
64 #define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
65   BOOST_JOIN(function_void_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
66 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
67   BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
68 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
69   BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
70 #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
71   BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
72 #define BOOST_FUNCTION_GET_MEMBER_INVOKER \
73   BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
74 #define BOOST_FUNCTION_GET_INVOKER \
75   BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
76 #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
77 
78 #ifndef BOOST_NO_VOID_RETURNS
79 #  define BOOST_FUNCTION_VOID_RETURN_TYPE void
80 #  define BOOST_FUNCTION_RETURN(X) X
81 #else
82 #  define BOOST_FUNCTION_VOID_RETURN_TYPE boost::detail::function::unusable
83 #  define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
84 #endif
85 
86 namespace boost {
87   namespace detail {
88     namespace function {
89       template<
90         typename FunctionPtr,
91         typename R BOOST_FUNCTION_COMMA
92         BOOST_FUNCTION_TEMPLATE_PARMS
93         >
94       struct BOOST_FUNCTION_FUNCTION_INVOKER
95       {
invokeboost::detail::function::BOOST_FUNCTION_FUNCTION_INVOKER96         static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
97                         BOOST_FUNCTION_PARMS)
98         {
99           FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
100           return f(BOOST_FUNCTION_ARGS);
101         }
102       };
103 
104       template<
105         typename FunctionPtr,
106         typename R BOOST_FUNCTION_COMMA
107         BOOST_FUNCTION_TEMPLATE_PARMS
108         >
109       struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
110       {
111         static BOOST_FUNCTION_VOID_RETURN_TYPE
invokeboost::detail::function::BOOST_FUNCTION_VOID_FUNCTION_INVOKER112         invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
113                BOOST_FUNCTION_PARMS)
114 
115         {
116           FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
117           BOOST_FUNCTION_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_FUNCTION_OBJ_INVOKER
127       {
invokeboost::detail::function::BOOST_FUNCTION_FUNCTION_OBJ_INVOKER128         static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
129                         BOOST_FUNCTION_PARMS)
130 
131         {
132           FunctionObj* f;
133           if (function_allows_small_object_optimization<FunctionObj>::value)
134             f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
135           else
136             f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
137           return (*f)(BOOST_FUNCTION_ARGS);
138         }
139       };
140 
141       template<
142         typename FunctionObj,
143         typename R BOOST_FUNCTION_COMMA
144         BOOST_FUNCTION_TEMPLATE_PARMS
145       >
146       struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
147       {
148         static BOOST_FUNCTION_VOID_RETURN_TYPE
invokeboost::detail::function::BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER149         invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
150                BOOST_FUNCTION_PARMS)
151 
152         {
153           FunctionObj* f;
154           if (function_allows_small_object_optimization<FunctionObj>::value)
155             f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
156           else
157             f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
158           BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
159         }
160       };
161 
162       template<
163         typename FunctionObj,
164         typename R BOOST_FUNCTION_COMMA
165         BOOST_FUNCTION_TEMPLATE_PARMS
166       >
167       struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
168       {
invokeboost::detail::function::BOOST_FUNCTION_FUNCTION_REF_INVOKER169         static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
170                         BOOST_FUNCTION_PARMS)
171 
172         {
173           FunctionObj* f =
174             reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
175           return (*f)(BOOST_FUNCTION_ARGS);
176         }
177       };
178 
179       template<
180         typename FunctionObj,
181         typename R BOOST_FUNCTION_COMMA
182         BOOST_FUNCTION_TEMPLATE_PARMS
183       >
184       struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
185       {
186         static BOOST_FUNCTION_VOID_RETURN_TYPE
invokeboost::detail::function::BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER187         invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
188                BOOST_FUNCTION_PARMS)
189 
190         {
191           FunctionObj* f =
192             reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
193           BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
194         }
195       };
196 
197 #if BOOST_FUNCTION_NUM_ARGS > 0
198       /* Handle invocation of member pointers. */
199       template<
200         typename MemberPtr,
201         typename R BOOST_FUNCTION_COMMA
202         BOOST_FUNCTION_TEMPLATE_PARMS
203       >
204       struct BOOST_FUNCTION_MEMBER_INVOKER
205       {
invokeboost::detail::function::BOOST_FUNCTION_MEMBER_INVOKER206         static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
207                         BOOST_FUNCTION_PARMS)
208 
209         {
210           MemberPtr* f =
211             reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
212           return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
213         }
214       };
215 
216       template<
217         typename MemberPtr,
218         typename R BOOST_FUNCTION_COMMA
219         BOOST_FUNCTION_TEMPLATE_PARMS
220       >
221       struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
222       {
223         static BOOST_FUNCTION_VOID_RETURN_TYPE
invokeboost::detail::function::BOOST_FUNCTION_VOID_MEMBER_INVOKER224         invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
225                BOOST_FUNCTION_PARMS)
226 
227         {
228           MemberPtr* f =
229             reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
230           BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
231         }
232       };
233 #endif
234 
235       template<
236         typename FunctionPtr,
237         typename R BOOST_FUNCTION_COMMA
238         BOOST_FUNCTION_TEMPLATE_PARMS
239       >
240       struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
241       {
242         typedef typename conditional<(is_void<R>::value),
243                             BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
244                             FunctionPtr,
245                             R BOOST_FUNCTION_COMMA
246                             BOOST_FUNCTION_TEMPLATE_ARGS
247                           >,
248                           BOOST_FUNCTION_FUNCTION_INVOKER<
249                             FunctionPtr,
250                             R BOOST_FUNCTION_COMMA
251                             BOOST_FUNCTION_TEMPLATE_ARGS
252                           >
253                        >::type type;
254       };
255 
256       template<
257         typename FunctionObj,
258         typename R BOOST_FUNCTION_COMMA
259         BOOST_FUNCTION_TEMPLATE_PARMS
260        >
261       struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
262       {
263         typedef typename conditional<(is_void<R>::value),
264                             BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
265                             FunctionObj,
266                             R BOOST_FUNCTION_COMMA
267                             BOOST_FUNCTION_TEMPLATE_ARGS
268                           >,
269                           BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
270                             FunctionObj,
271                             R BOOST_FUNCTION_COMMA
272                             BOOST_FUNCTION_TEMPLATE_ARGS
273                           >
274                        >::type type;
275       };
276 
277       template<
278         typename FunctionObj,
279         typename R BOOST_FUNCTION_COMMA
280         BOOST_FUNCTION_TEMPLATE_PARMS
281        >
282       struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
283       {
284         typedef typename conditional<(is_void<R>::value),
285                             BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
286                             FunctionObj,
287                             R BOOST_FUNCTION_COMMA
288                             BOOST_FUNCTION_TEMPLATE_ARGS
289                           >,
290                           BOOST_FUNCTION_FUNCTION_REF_INVOKER<
291                             FunctionObj,
292                             R BOOST_FUNCTION_COMMA
293                             BOOST_FUNCTION_TEMPLATE_ARGS
294                           >
295                        >::type type;
296       };
297 
298 #if BOOST_FUNCTION_NUM_ARGS > 0
299       /* Retrieve the appropriate invoker for a member pointer.  */
300       template<
301         typename MemberPtr,
302         typename R BOOST_FUNCTION_COMMA
303         BOOST_FUNCTION_TEMPLATE_PARMS
304        >
305       struct BOOST_FUNCTION_GET_MEMBER_INVOKER
306       {
307         typedef typename conditional<(is_void<R>::value),
308                             BOOST_FUNCTION_VOID_MEMBER_INVOKER<
309                             MemberPtr,
310                             R BOOST_FUNCTION_COMMA
311                             BOOST_FUNCTION_TEMPLATE_ARGS
312                           >,
313                           BOOST_FUNCTION_MEMBER_INVOKER<
314                             MemberPtr,
315                             R BOOST_FUNCTION_COMMA
316                             BOOST_FUNCTION_TEMPLATE_ARGS
317                           >
318                        >::type type;
319       };
320 #endif
321 
322       /* Given the tag returned by get_function_tag, retrieve the
323          actual invoker that will be used for the given function
324          object.
325 
326          Each specialization contains an "apply" nested class template
327          that accepts the function object, return type, function
328          argument types, and allocator. The resulting "apply" class
329          contains two typedefs, "invoker_type" and "manager_type",
330          which correspond to the invoker and manager types. */
331       template<typename Tag>
332       struct BOOST_FUNCTION_GET_INVOKER { };
333 
334       /* Retrieve the invoker for a function pointer. */
335       template<>
336       struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
337       {
338         template<typename FunctionPtr,
339                  typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
340         struct apply
341         {
342           typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
343                              FunctionPtr,
344                              R BOOST_FUNCTION_COMMA
345                              BOOST_FUNCTION_TEMPLATE_ARGS
346                            >::type
347             invoker_type;
348 
349           typedef functor_manager<FunctionPtr> manager_type;
350         };
351 
352         template<typename FunctionPtr, typename Allocator,
353                  typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
354         struct apply_a
355         {
356           typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
357                              FunctionPtr,
358                              R BOOST_FUNCTION_COMMA
359                              BOOST_FUNCTION_TEMPLATE_ARGS
360                            >::type
361             invoker_type;
362 
363           typedef functor_manager<FunctionPtr> manager_type;
364         };
365       };
366 
367 #if BOOST_FUNCTION_NUM_ARGS > 0
368       /* Retrieve the invoker for a member pointer. */
369       template<>
370       struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
371       {
372         template<typename MemberPtr,
373                  typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
374         struct apply
375         {
376           typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
377                              MemberPtr,
378                              R BOOST_FUNCTION_COMMA
379                              BOOST_FUNCTION_TEMPLATE_ARGS
380                            >::type
381             invoker_type;
382 
383           typedef functor_manager<MemberPtr> manager_type;
384         };
385 
386         template<typename MemberPtr, typename Allocator,
387                  typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
388         struct apply_a
389         {
390           typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
391                              MemberPtr,
392                              R BOOST_FUNCTION_COMMA
393                              BOOST_FUNCTION_TEMPLATE_ARGS
394                            >::type
395             invoker_type;
396 
397           typedef functor_manager<MemberPtr> manager_type;
398         };
399       };
400 #endif
401 
402       /* Retrieve the invoker for a function object. */
403       template<>
404       struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
405       {
406         template<typename FunctionObj,
407                  typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
408         struct apply
409         {
410           typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
411                              FunctionObj,
412                              R BOOST_FUNCTION_COMMA
413                              BOOST_FUNCTION_TEMPLATE_ARGS
414                            >::type
415             invoker_type;
416 
417           typedef functor_manager<FunctionObj> manager_type;
418         };
419 
420         template<typename FunctionObj, typename Allocator,
421                  typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
422         struct apply_a
423         {
424           typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
425                              FunctionObj,
426                              R BOOST_FUNCTION_COMMA
427                              BOOST_FUNCTION_TEMPLATE_ARGS
428                            >::type
429             invoker_type;
430 
431           typedef functor_manager_a<FunctionObj, Allocator> manager_type;
432         };
433       };
434 
435       /* Retrieve the invoker for a reference to a function object. */
436       template<>
437       struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
438       {
439         template<typename RefWrapper,
440                  typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
441         struct apply
442         {
443           typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
444                              typename RefWrapper::type,
445                              R BOOST_FUNCTION_COMMA
446                              BOOST_FUNCTION_TEMPLATE_ARGS
447                            >::type
448             invoker_type;
449 
450           typedef reference_manager<typename RefWrapper::type> manager_type;
451         };
452 
453         template<typename RefWrapper, typename Allocator,
454                  typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
455         struct apply_a
456         {
457           typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
458                              typename RefWrapper::type,
459                              R BOOST_FUNCTION_COMMA
460                              BOOST_FUNCTION_TEMPLATE_ARGS
461                            >::type
462             invoker_type;
463 
464           typedef reference_manager<typename RefWrapper::type> manager_type;
465         };
466       };
467 
468 
469       /**
470        * vtable for a specific boost::function instance. This
471        * structure must be an aggregate so that we can use static
472        * initialization in boost::function's assign_to and assign_to_a
473        * members. It therefore cannot have any constructors,
474        * destructors, base classes, etc.
475        */
476       template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
477       struct BOOST_FUNCTION_VTABLE
478       {
479 #ifndef BOOST_NO_VOID_RETURNS
480         typedef R         result_type;
481 #else
482         typedef typename function_return_type<R>::type result_type;
483 #endif // BOOST_NO_VOID_RETURNS
484 
485         typedef result_type (*invoker_type)(function_buffer&
486                                             BOOST_FUNCTION_COMMA
487                                             BOOST_FUNCTION_TEMPLATE_ARGS);
488 
489         template<typename F>
assign_toboost::detail::function::BOOST_FUNCTION_VTABLE490         bool assign_to(F f, function_buffer& functor) const
491         {
492           typedef typename get_function_tag<F>::type tag;
493           return assign_to(f, functor, tag());
494         }
495         template<typename F,typename Allocator>
assign_to_aboost::detail::function::BOOST_FUNCTION_VTABLE496         bool assign_to_a(F f, function_buffer& functor, Allocator a) const
497         {
498           typedef typename get_function_tag<F>::type tag;
499           return assign_to_a(f, functor, a, tag());
500         }
501 
clearboost::detail::function::BOOST_FUNCTION_VTABLE502         void clear(function_buffer& functor) const
503         {
504           if (base.manager)
505             base.manager(functor, functor, destroy_functor_tag);
506         }
507 
508       private:
509         // Function pointers
510         template<typename FunctionPtr>
511         bool
assign_toboost::detail::function::BOOST_FUNCTION_VTABLE512         assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
513         {
514           this->clear(functor);
515           if (f) {
516             // should be a reinterpret cast, but some compilers insist
517             // on giving cv-qualifiers to free functions
518             functor.members.func_ptr = reinterpret_cast<void (*)()>(f);
519             return true;
520           } else {
521             return false;
522           }
523         }
524         template<typename FunctionPtr,typename Allocator>
525         bool
assign_to_aboost::detail::function::BOOST_FUNCTION_VTABLE526         assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
527         {
528           return assign_to(f,functor,function_ptr_tag());
529         }
530 
531         // Member pointers
532 #if BOOST_FUNCTION_NUM_ARGS > 0
533         template<typename MemberPtr>
assign_toboost::detail::function::BOOST_FUNCTION_VTABLE534         bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
535         {
536           // DPG TBD: Add explicit support for member function
537           // objects, so we invoke through mem_fn() but we retain the
538           // right target_type() values.
539           if (f) {
540             this->assign_to(boost::mem_fn(f), functor);
541             return true;
542           } else {
543             return false;
544           }
545         }
546         template<typename MemberPtr,typename Allocator>
assign_to_aboost::detail::function::BOOST_FUNCTION_VTABLE547         bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag) const
548         {
549           // DPG TBD: Add explicit support for member function
550           // objects, so we invoke through mem_fn() but we retain the
551           // right target_type() values.
552           if (f) {
553             this->assign_to_a(boost::mem_fn(f), functor, a);
554             return true;
555           } else {
556             return false;
557           }
558         }
559 #endif // BOOST_FUNCTION_NUM_ARGS > 0
560 
561         // Function objects
562         // Assign to a function object using the small object optimization
563         template<typename FunctionObj>
564         void
assign_functorboost::detail::function::BOOST_FUNCTION_VTABLE565         assign_functor(FunctionObj f, function_buffer& functor, true_type) const
566         {
567           new (reinterpret_cast<void*>(functor.data)) FunctionObj(f);
568         }
569         template<typename FunctionObj,typename Allocator>
570         void
assign_functor_aboost::detail::function::BOOST_FUNCTION_VTABLE571         assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, true_type) const
572         {
573           assign_functor(f,functor,true_type());
574         }
575 
576         // Assign to a function object allocated on the heap.
577         template<typename FunctionObj>
578         void
assign_functorboost::detail::function::BOOST_FUNCTION_VTABLE579         assign_functor(FunctionObj f, function_buffer& functor, false_type) const
580         {
581           functor.members.obj_ptr = new FunctionObj(f);
582         }
583         template<typename FunctionObj,typename Allocator>
584         void
assign_functor_aboost::detail::function::BOOST_FUNCTION_VTABLE585         assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, false_type) const
586         {
587           typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
588 #if defined(BOOST_NO_CXX11_ALLOCATOR)
589           typedef typename Allocator::template rebind<functor_wrapper_type>::other
590             wrapper_allocator_type;
591           typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
592 #else
593           using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
594           using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
595 #endif
596           wrapper_allocator_type wrapper_allocator(a);
597           wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
598 #if defined(BOOST_NO_CXX11_ALLOCATOR)
599           wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
600 #else
601           std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, functor_wrapper_type(f,a));
602 #endif
603           functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
604           functor.members.obj_ptr = new_f;
605         }
606 
607         template<typename FunctionObj>
608         bool
assign_toboost::detail::function::BOOST_FUNCTION_VTABLE609         assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
610         {
611           if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
612             assign_functor(f, functor,
613                            integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>());
614             return true;
615           } else {
616             return false;
617           }
618         }
619         template<typename FunctionObj,typename Allocator>
620         bool
assign_to_aboost::detail::function::BOOST_FUNCTION_VTABLE621         assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
622         {
623           if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
624             assign_functor_a(f, functor, a,
625                            integral_constant<bool, (function_allows_small_object_optimization<FunctionObj>::value)>());
626             return true;
627           } else {
628             return false;
629           }
630         }
631 
632         // Reference to a function object
633         template<typename FunctionObj>
634         bool
assign_toboost::detail::function::BOOST_FUNCTION_VTABLE635         assign_to(const reference_wrapper<FunctionObj>& f,
636                   function_buffer& functor, function_obj_ref_tag) const
637         {
638           functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer());
639           functor.members.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
640           functor.members.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
641           return true;
642         }
643         template<typename FunctionObj,typename Allocator>
644         bool
assign_to_aboost::detail::function::BOOST_FUNCTION_VTABLE645         assign_to_a(const reference_wrapper<FunctionObj>& f,
646                   function_buffer& functor, Allocator, function_obj_ref_tag) const
647         {
648           return assign_to(f,functor,function_obj_ref_tag());
649         }
650 
651       public:
652         vtable_base base;
653         invoker_type invoker;
654       };
655     } // end namespace function
656   } // end namespace detail
657 
658   template<
659     typename R BOOST_FUNCTION_COMMA
660     BOOST_FUNCTION_TEMPLATE_PARMS
661   >
662   class BOOST_FUNCTION_FUNCTION : public function_base
663   {
664   public:
665 #ifndef BOOST_NO_VOID_RETURNS
666     typedef R         result_type;
667 #else
668     typedef  typename boost::detail::function::function_return_type<R>::type
669       result_type;
670 #endif // BOOST_NO_VOID_RETURNS
671 
672   private:
673     typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
674               R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
675       vtable_type;
676 
get_vtable() const677     vtable_type* get_vtable() const {
678       return reinterpret_cast<vtable_type*>(
679                reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
680     }
681 
682     struct clear_type {};
683 
684   public:
685     BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
686 
687     // add signature for boost::lambda
688     template<typename Args>
689     struct sig
690     {
691       typedef result_type type;
692     };
693 
694 #if BOOST_FUNCTION_NUM_ARGS == 1
695     typedef T0 argument_type;
696 #elif BOOST_FUNCTION_NUM_ARGS == 2
697     typedef T0 first_argument_type;
698     typedef T1 second_argument_type;
699 #endif
700 
701     BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
702     BOOST_FUNCTION_ARG_TYPES
703 
704     typedef BOOST_FUNCTION_FUNCTION self_type;
705 
BOOST_FUNCTION_FUNCTION()706     BOOST_DEFAULTED_FUNCTION(BOOST_FUNCTION_FUNCTION(), : function_base() {})
707 
708     // MSVC chokes if the following two constructors are collapsed into
709     // one with a default parameter.
710     template<typename Functor>
711     BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f
712 #ifndef BOOST_NO_SFINAE
713                             ,typename boost::enable_if_<
714                              !(is_integral<Functor>::value),
715                                         int>::type = 0
716 #endif // BOOST_NO_SFINAE
717                             ) :
718       function_base()
719     {
720       this->assign_to(f);
721     }
722     template<typename Functor,typename Allocator>
BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX (const &)f,Allocator a,typename boost::enable_if_<!(is_integral<Functor>::value),int>::type=0)723     BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
724 #ifndef BOOST_NO_SFINAE
725                             ,typename boost::enable_if_<
726                               !(is_integral<Functor>::value),
727                                         int>::type = 0
728 #endif // BOOST_NO_SFINAE
729                             ) :
730       function_base()
731     {
732       this->assign_to_a(f,a);
733     }
734 
735 #ifndef BOOST_NO_SFINAE
BOOST_FUNCTION_FUNCTION(clear_type *)736     BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
737 #else
BOOST_FUNCTION_FUNCTION(int zero)738     BOOST_FUNCTION_FUNCTION(int zero) : function_base()
739     {
740       BOOST_ASSERT(zero == 0);
741     }
742 #endif
743 
BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION & f)744     BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
745     {
746       this->assign_to_own(f);
747     }
748 
749 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION && f)750     BOOST_FUNCTION_FUNCTION(BOOST_FUNCTION_FUNCTION&& f) : function_base()
751     {
752       this->move_assign(f);
753     }
754 #endif
755 
~BOOST_FUNCTION_FUNCTION()756     ~BOOST_FUNCTION_FUNCTION() { clear(); }
757 
operator ()(BOOST_FUNCTION_PARMS) const758     result_type operator()(BOOST_FUNCTION_PARMS) const
759     {
760       if (this->empty())
761         boost::throw_exception(bad_function_call());
762 
763       return get_vtable()->invoker
764                (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
765     }
766 
767     // The distinction between when to use BOOST_FUNCTION_FUNCTION and
768     // when to use self_type is obnoxious. MSVC cannot handle self_type as
769     // the return type of these assignment operators, but Borland C++ cannot
770     // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
771     // construct.
772     template<typename Functor>
773 #ifndef BOOST_NO_SFINAE
774     typename boost::enable_if_<
775                   !(is_integral<Functor>::value),
776                BOOST_FUNCTION_FUNCTION&>::type
777 #else
778     BOOST_FUNCTION_FUNCTION&
779 #endif
operator =(Functor BOOST_FUNCTION_TARGET_FIX (const &)f)780     operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
781     {
782       this->clear();
783       BOOST_TRY  {
784         this->assign_to(f);
785       } BOOST_CATCH (...) {
786         vtable = 0;
787         BOOST_RETHROW;
788       }
789       BOOST_CATCH_END
790       return *this;
791     }
792     template<typename Functor,typename Allocator>
assign(Functor BOOST_FUNCTION_TARGET_FIX (const &)f,Allocator a)793     void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
794     {
795       this->clear();
796       BOOST_TRY{
797         this->assign_to_a(f,a);
798       } BOOST_CATCH (...) {
799         vtable = 0;
800         BOOST_RETHROW;
801       }
802       BOOST_CATCH_END
803     }
804 
805 #ifndef BOOST_NO_SFINAE
operator =(clear_type *)806     BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
807     {
808       this->clear();
809       return *this;
810     }
811 #else
operator =(int zero)812     BOOST_FUNCTION_FUNCTION& operator=(int zero)
813     {
814       BOOST_ASSERT(zero == 0);
815       this->clear();
816       return *this;
817     }
818 #endif
819 
820     // Assignment from another BOOST_FUNCTION_FUNCTION
operator =(const BOOST_FUNCTION_FUNCTION & f)821     BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
822     {
823       if (&f == this)
824         return *this;
825 
826       this->clear();
827       BOOST_TRY {
828         this->assign_to_own(f);
829       } BOOST_CATCH (...) {
830         vtable = 0;
831         BOOST_RETHROW;
832       }
833       BOOST_CATCH_END
834       return *this;
835     }
836 
837 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
838     // Move assignment from another BOOST_FUNCTION_FUNCTION
operator =(BOOST_FUNCTION_FUNCTION && f)839     BOOST_FUNCTION_FUNCTION& operator=(BOOST_FUNCTION_FUNCTION&& f)
840     {
841       if (&f == this)
842         return *this;
843 
844       this->clear();
845       BOOST_TRY {
846         this->move_assign(f);
847       } BOOST_CATCH (...) {
848         vtable = 0;
849         BOOST_RETHROW;
850       }
851       BOOST_CATCH_END
852       return *this;
853     }
854 #endif
855 
swap(BOOST_FUNCTION_FUNCTION & other)856     void swap(BOOST_FUNCTION_FUNCTION& other)
857     {
858       if (&other == this)
859         return;
860 
861       BOOST_FUNCTION_FUNCTION tmp;
862       tmp.move_assign(*this);
863       this->move_assign(other);
864       other.move_assign(tmp);
865     }
866 
867     // Clear out a target, if there is one
clear()868     void clear()
869     {
870       if (vtable) {
871         if (!this->has_trivial_copy_and_destroy())
872           get_vtable()->clear(this->functor);
873         vtable = 0;
874       }
875     }
876 
877 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
878     // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
operator bool() const879     operator bool () const { return !this->empty(); }
880 #else
881   private:
882     struct dummy {
nonnullboost::BOOST_FUNCTION_FUNCTION::dummy883       void nonnull() {}
884     };
885 
886     typedef void (dummy::*safe_bool)();
887 
888   public:
operator safe_bool() const889     operator safe_bool () const
890       { return (this->empty())? 0 : &dummy::nonnull; }
891 
operator !() const892     bool operator!() const
893       { return this->empty(); }
894 #endif
895 
896   private:
assign_to_own(const BOOST_FUNCTION_FUNCTION & f)897     void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
898     {
899       if (!f.empty()) {
900         this->vtable = f.vtable;
901         if (this->has_trivial_copy_and_destroy()) {
902           // Don't operate on storage directly since union type doesn't relax
903           // strict aliasing rules, despite of having member char type.
904 #         if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
905 #           pragma GCC diagnostic push
906             // This warning is technically correct, but we don't want to pay the price for initializing
907             // just to silence a warning: https://github.com/boostorg/function/issues/27
908           //#           pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
909 #         endif
910           std::memcpy(this->functor.data, f.functor.data, sizeof(boost::detail::function::function_buffer));
911 #         if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
912 #           pragma GCC diagnostic pop
913 #         endif
914         } else
915           get_vtable()->base.manager(f.functor, this->functor,
916                                      boost::detail::function::clone_functor_tag);
917       }
918     }
919 
920     template<typename Functor>
assign_to(Functor f)921     void assign_to(Functor f)
922     {
923       using boost::detail::function::vtable_base;
924 
925       typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
926       typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
927       typedef typename get_invoker::
928                          template apply<Functor, R BOOST_FUNCTION_COMMA
929                         BOOST_FUNCTION_TEMPLATE_ARGS>
930         handler_type;
931 
932       typedef typename handler_type::invoker_type invoker_type;
933       typedef typename handler_type::manager_type manager_type;
934 
935       // Note: it is extremely important that this initialization use
936       // static initialization. Otherwise, we will have a race
937       // condition here in multi-threaded code. See
938       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
939       static const vtable_type stored_vtable =
940         { { &manager_type::manage }, &invoker_type::invoke };
941 
942       if (stored_vtable.assign_to(f, functor)) {
943         std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
944         // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
945         if (boost::has_trivial_copy_constructor<Functor>::value &&
946             boost::has_trivial_destructor<Functor>::value &&
947             boost::detail::function::function_allows_small_object_optimization<Functor>::value)
948           value |= static_cast<std::size_t>(0x01);
949         vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
950       } else
951         vtable = 0;
952     }
953 
954     template<typename Functor,typename Allocator>
assign_to_a(Functor f,Allocator a)955     void assign_to_a(Functor f,Allocator a)
956     {
957       using boost::detail::function::vtable_base;
958 
959       typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
960       typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
961       typedef typename get_invoker::
962                          template apply_a<Functor, Allocator, R BOOST_FUNCTION_COMMA
963                          BOOST_FUNCTION_TEMPLATE_ARGS>
964         handler_type;
965 
966       typedef typename handler_type::invoker_type invoker_type;
967       typedef typename handler_type::manager_type manager_type;
968 
969       // Note: it is extremely important that this initialization use
970       // static initialization. Otherwise, we will have a race
971       // condition here in multi-threaded code. See
972       // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
973       static const vtable_type stored_vtable =
974         { { &manager_type::manage }, &invoker_type::invoke };
975 
976       if (stored_vtable.assign_to_a(f, functor, a)) {
977         std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
978         // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
979         if (boost::has_trivial_copy_constructor<Functor>::value &&
980             boost::has_trivial_destructor<Functor>::value &&
981             boost::detail::function::function_allows_small_object_optimization<Functor>::value)
982           value |= static_cast<std::size_t>(0x01);
983         vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
984       } else
985         vtable = 0;
986     }
987 
988     // Moves the value from the specified argument to *this. If the argument
989     // has its function object allocated on the heap, move_assign will pass
990     // its buffer to *this, and set the argument's buffer pointer to NULL.
move_assign(BOOST_FUNCTION_FUNCTION & f)991     void move_assign(BOOST_FUNCTION_FUNCTION& f)
992     {
993       if (&f == this)
994         return;
995 
996       BOOST_TRY {
997         if (!f.empty()) {
998           this->vtable = f.vtable;
999           if (this->has_trivial_copy_and_destroy()) {
1000             // Don't operate on storage directly since union type doesn't relax
1001             // strict aliasing rules, despite of having member char type.
1002 #           if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
1003 #             pragma GCC diagnostic push
1004               // This warning is technically correct, but we don't want to pay the price for initializing
1005               // just to silence a warning: https://github.com/boostorg/function/issues/27
1006             //#             pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
1007 #           endif
1008             std::memcpy(this->functor.data, f.functor.data, sizeof(this->functor.data));
1009 #           if defined(BOOST_GCC) && (BOOST_GCC >= 40700)
1010 #             pragma GCC diagnostic pop
1011 #           endif
1012           } else
1013             get_vtable()->base.manager(f.functor, this->functor,
1014                                      boost::detail::function::move_functor_tag);
1015           f.vtable = 0;
1016         } else {
1017           clear();
1018         }
1019       } BOOST_CATCH (...) {
1020         vtable = 0;
1021         BOOST_RETHROW;
1022       }
1023       BOOST_CATCH_END
1024     }
1025   };
1026 
1027   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
swap(BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> & f1,BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> & f2)1028   inline void swap(BOOST_FUNCTION_FUNCTION<
1029                      R BOOST_FUNCTION_COMMA
1030                      BOOST_FUNCTION_TEMPLATE_ARGS
1031                    >& f1,
1032                    BOOST_FUNCTION_FUNCTION<
1033                      R BOOST_FUNCTION_COMMA
1034                      BOOST_FUNCTION_TEMPLATE_ARGS
1035                    >& f2)
1036   {
1037     f1.swap(f2);
1038   }
1039 
1040 // Poison comparisons between boost::function objects of the same type.
1041 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1042   void operator==(const BOOST_FUNCTION_FUNCTION<
1043                           R BOOST_FUNCTION_COMMA
1044                           BOOST_FUNCTION_TEMPLATE_ARGS>&,
1045                   const BOOST_FUNCTION_FUNCTION<
1046                           R BOOST_FUNCTION_COMMA
1047                           BOOST_FUNCTION_TEMPLATE_ARGS>&);
1048 template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
1049   void operator!=(const BOOST_FUNCTION_FUNCTION<
1050                           R BOOST_FUNCTION_COMMA
1051                           BOOST_FUNCTION_TEMPLATE_ARGS>&,
1052                   const BOOST_FUNCTION_FUNCTION<
1053                           R BOOST_FUNCTION_COMMA
1054                           BOOST_FUNCTION_TEMPLATE_ARGS>& );
1055 
1056 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
1057 
1058 #if BOOST_FUNCTION_NUM_ARGS == 0
1059 #define BOOST_FUNCTION_PARTIAL_SPEC R (void)
1060 #else
1061 #define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_FUNCTION_TEMPLATE_ARGS)
1062 #endif
1063 
1064 template<typename R BOOST_FUNCTION_COMMA
1065          BOOST_FUNCTION_TEMPLATE_PARMS>
1066 class function<BOOST_FUNCTION_PARTIAL_SPEC>
1067   : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
1068 {
1069   typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
1070   typedef function self_type;
1071 
1072   struct clear_type {};
1073 
1074 public:
1075 
function()1076   BOOST_DEFAULTED_FUNCTION(function(), : base_type() {})
1077 
1078   template<typename Functor>
1079   function(Functor f
1080 #ifndef BOOST_NO_SFINAE
1081            ,typename boost::enable_if_<
1082                           !(is_integral<Functor>::value),
1083                        int>::type = 0
1084 #endif
1085            ) :
1086     base_type(f)
1087   {
1088   }
1089   template<typename Functor,typename Allocator>
function(Functor f,Allocator a,typename boost::enable_if_<!(is_integral<Functor>::value),int>::type=0)1090   function(Functor f, Allocator a
1091 #ifndef BOOST_NO_SFINAE
1092            ,typename boost::enable_if_<
1093                            !(is_integral<Functor>::value),
1094                        int>::type = 0
1095 #endif
1096            ) :
1097     base_type(f,a)
1098   {
1099   }
1100 
1101 #ifndef BOOST_NO_SFINAE
function(clear_type *)1102   function(clear_type*) : base_type() {}
1103 #endif
1104 
function(const self_type & f)1105   function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
1106 
function(const base_type & f)1107   function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
1108 
1109 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
1110   // Move constructors
function(self_type && f)1111   function(self_type&& f): base_type(static_cast<base_type&&>(f)){}
function(base_type && f)1112   function(base_type&& f): base_type(static_cast<base_type&&>(f)){}
1113 #endif
1114 
operator =(const self_type & f)1115   self_type& operator=(const self_type& f)
1116   {
1117     self_type(f).swap(*this);
1118     return *this;
1119   }
1120 
1121 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =(self_type && f)1122   self_type& operator=(self_type&& f)
1123   {
1124     self_type(static_cast<self_type&&>(f)).swap(*this);
1125     return *this;
1126   }
1127 #endif
1128 
1129   template<typename Functor>
1130 #ifndef BOOST_NO_SFINAE
1131   typename boost::enable_if_<
1132                          !(is_integral<Functor>::value),
1133                       self_type&>::type
1134 #else
1135   self_type&
1136 #endif
operator =(Functor f)1137   operator=(Functor f)
1138   {
1139     self_type(f).swap(*this);
1140     return *this;
1141   }
1142 
1143 #ifndef BOOST_NO_SFINAE
operator =(clear_type *)1144   self_type& operator=(clear_type*)
1145   {
1146     this->clear();
1147     return *this;
1148   }
1149 #endif
1150 
operator =(const base_type & f)1151   self_type& operator=(const base_type& f)
1152   {
1153     self_type(f).swap(*this);
1154     return *this;
1155   }
1156 
1157 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
operator =(base_type && f)1158   self_type& operator=(base_type&& f)
1159   {
1160     self_type(static_cast<base_type&&>(f)).swap(*this);
1161     return *this;
1162   }
1163 #endif
1164 };
1165 
1166 #undef BOOST_FUNCTION_PARTIAL_SPEC
1167 #endif // have partial specialization
1168 
1169 } // end namespace boost
1170 
1171 // Cleanup after ourselves...
1172 #undef BOOST_FUNCTION_VTABLE
1173 #undef BOOST_FUNCTION_COMMA
1174 #undef BOOST_FUNCTION_FUNCTION
1175 #undef BOOST_FUNCTION_FUNCTION_INVOKER
1176 #undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
1177 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
1178 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
1179 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
1180 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
1181 #undef BOOST_FUNCTION_MEMBER_INVOKER
1182 #undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
1183 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
1184 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
1185 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
1186 #undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
1187 #undef BOOST_FUNCTION_GET_INVOKER
1188 #undef BOOST_FUNCTION_TEMPLATE_PARMS
1189 #undef BOOST_FUNCTION_TEMPLATE_ARGS
1190 #undef BOOST_FUNCTION_PARMS
1191 #undef BOOST_FUNCTION_PARM
1192 #ifdef BOOST_FUNCTION_ARG
1193 #   undef BOOST_FUNCTION_ARG
1194 #endif
1195 #undef BOOST_FUNCTION_ARGS
1196 #undef BOOST_FUNCTION_ARG_TYPE
1197 #undef BOOST_FUNCTION_ARG_TYPES
1198 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
1199 #undef BOOST_FUNCTION_RETURN
1200 
1201 #if defined(BOOST_MSVC)
1202 #   pragma warning( pop )
1203 #endif
1204