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 #ifndef BOOST_FUNCTION_BASE_HEADER
12 #define BOOST_FUNCTION_BASE_HEADER
13 
14 #include <stdexcept>
15 #include <string>
16 #include <memory>
17 #include <new>
18 #include <boost/config.hpp>
19 #include <boost/detail/sp_typeinfo.hpp>
20 #include <boost/assert.hpp>
21 #include <boost/integer.hpp>
22 #include <boost/type_traits/has_trivial_copy.hpp>
23 #include <boost/type_traits/has_trivial_destructor.hpp>
24 #include <boost/type_traits/is_const.hpp>
25 #include <boost/type_traits/is_integral.hpp>
26 #include <boost/type_traits/is_volatile.hpp>
27 #include <boost/type_traits/composite_traits.hpp>
28 #include <boost/ref.hpp>
29 #include <boost/mpl/if.hpp>
30 #include <boost/detail/workaround.hpp>
31 #include <boost/type_traits/alignment_of.hpp>
32 #ifndef BOOST_NO_SFINAE
33 #  include "boost/utility/enable_if.hpp"
34 #else
35 #  include "boost/mpl/bool.hpp"
36 #endif
37 #include <boost/function_equal.hpp>
38 #include <boost/function/function_fwd.hpp>
39 
40 #if defined(BOOST_MSVC)
41 #   pragma warning( push )
42 #   pragma warning( disable : 4793 ) // complaint about native code generation
43 #   pragma warning( disable : 4127 ) // "conditional expression is constant"
44 #endif
45 
46 // Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
47 #ifdef BOOST_NO_STD_TYPEINFO
48 // Embedded VC++ does not have type_info in namespace std
49 #  define BOOST_FUNCTION_STD_NS
50 #else
51 #  define BOOST_FUNCTION_STD_NS std
52 #endif
53 
54 // Borrowed from Boost.Python library: determines the cases where we
55 // need to use std::type_info::name to compare instead of operator==.
56 #if defined( BOOST_NO_TYPEID )
57 #  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
58 #elif defined(__GNUC__) \
59  || defined(_AIX) \
60  || (   defined(__sgi) && defined(__host_mips))
61 #  include <cstring>
62 #  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
63      (std::strcmp((X).name(),(Y).name()) == 0)
64 # else
65 #  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
66 #endif
67 
68 #if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
69 #  define BOOST_FUNCTION_TARGET_FIX(x) x
70 #else
71 #  define BOOST_FUNCTION_TARGET_FIX(x)
72 #endif // __ICL etc
73 
74 #  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)              \
75       typename ::boost::enable_if_c<          \
76                            !(::boost::is_integral<Functor>::value), \
77                            Type>::type
78 
79 namespace boost {
80   namespace detail {
81     namespace function {
82       class X;
83 
84       /**
85        * A buffer used to store small function objects in
86        * boost::function. It is a union containing function pointers,
87        * object pointers, and a structure that resembles a bound
88        * member function pointer.
89        */
90       union function_buffer
91       {
92         // For pointers to function objects
93         mutable void* obj_ptr;
94 
95         // For pointers to std::type_info objects
96         struct type_t {
97           // (get_functor_type_tag, check_functor_type_tag).
98           const detail::sp_typeinfo* type;
99 
100           // Whether the type is const-qualified.
101           bool const_qualified;
102           // Whether the type is volatile-qualified.
103           bool volatile_qualified;
104         } type;
105 
106         // For function pointers of all kinds
107         mutable void (*func_ptr)();
108 
109         // For bound member pointers
110         struct bound_memfunc_ptr_t {
111           void (X::*memfunc_ptr)(int);
112           void* obj_ptr;
113         } bound_memfunc_ptr;
114 
115         // For references to function objects. We explicitly keep
116         // track of the cv-qualifiers on the object referenced.
117         struct obj_ref_t {
118           mutable void* obj_ptr;
119           bool is_const_qualified;
120           bool is_volatile_qualified;
121         } obj_ref;
122 
123         // To relax aliasing constraints
124         mutable char data;
125       };
126 
127       /**
128        * The unusable class is a placeholder for unused function arguments
129        * It is also completely unusable except that it constructable from
130        * anything. This helps compilers without partial specialization to
131        * handle Boost.Function objects returning void.
132        */
133       struct unusable
134       {
unusableboost::detail::function::unusable135         unusable() {}
unusableboost::detail::function::unusable136         template<typename T> unusable(const T&) {}
137       };
138 
139       /* Determine the return type. This supports compilers that do not support
140        * void returns or partial specialization by silently changing the return
141        * type to "unusable".
142        */
143       template<typename T> struct function_return_type { typedef T type; };
144 
145       template<>
146       struct function_return_type<void>
147       {
148         typedef unusable type;
149       };
150 
151       // The operation type to perform on the given functor/function pointer
152       enum functor_manager_operation_type {
153         clone_functor_tag,
154         move_functor_tag,
155         destroy_functor_tag,
156         check_functor_type_tag,
157         get_functor_type_tag
158       };
159 
160       // Tags used to decide between different types of functions
161       struct function_ptr_tag {};
162       struct function_obj_tag {};
163       struct member_ptr_tag {};
164       struct function_obj_ref_tag {};
165 
166       template<typename F>
167       class get_function_tag
168       {
169         typedef typename mpl::if_c<(is_pointer<F>::value),
170                                    function_ptr_tag,
171                                    function_obj_tag>::type ptr_or_obj_tag;
172 
173         typedef typename mpl::if_c<(is_member_pointer<F>::value),
174                                    member_ptr_tag,
175                                    ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
176 
177         typedef typename mpl::if_c<(is_reference_wrapper<F>::value),
178                                    function_obj_ref_tag,
179                                    ptr_or_obj_or_mem_tag>::type or_ref_tag;
180 
181       public:
182         typedef or_ref_tag type;
183       };
184 
185       // The trivial manager does nothing but return the same pointer (if we
186       // are cloning) or return the null pointer (if we are deleting).
187       template<typename F>
188       struct reference_manager
189       {
190         static inline void
manageboost::detail::function::reference_manager191         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
192                functor_manager_operation_type op)
193         {
194           switch (op) {
195           case clone_functor_tag:
196             out_buffer.obj_ref = in_buffer.obj_ref;
197             return;
198 
199           case move_functor_tag:
200             out_buffer.obj_ref = in_buffer.obj_ref;
201             in_buffer.obj_ref.obj_ptr = 0;
202             return;
203 
204           case destroy_functor_tag:
205             out_buffer.obj_ref.obj_ptr = 0;
206             return;
207 
208           case check_functor_type_tag:
209             {
210               const detail::sp_typeinfo& check_type
211                 = *out_buffer.type.type;
212 
213               // Check whether we have the same type. We can add
214               // cv-qualifiers, but we can't take them away.
215               if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(F))
216                   && (!in_buffer.obj_ref.is_const_qualified
217                       || out_buffer.type.const_qualified)
218                   && (!in_buffer.obj_ref.is_volatile_qualified
219                       || out_buffer.type.volatile_qualified))
220                 out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
221               else
222                 out_buffer.obj_ptr = 0;
223             }
224             return;
225 
226           case get_functor_type_tag:
227             out_buffer.type.type = &BOOST_SP_TYPEID(F);
228             out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
229             out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
230             return;
231           }
232         }
233       };
234 
235       /**
236        * Determine if boost::function can use the small-object
237        * optimization with the function object type F.
238        */
239       template<typename F>
240       struct function_allows_small_object_optimization
241       {
242         BOOST_STATIC_CONSTANT
243           (bool,
244            value = ((sizeof(F) <= sizeof(function_buffer) &&
245                      (alignment_of<function_buffer>::value
246                       % alignment_of<F>::value == 0))));
247       };
248 
249       template <typename F,typename A>
250       struct functor_wrapper: public F, public A
251       {
functor_wrapperboost::detail::function::functor_wrapper252         functor_wrapper( F f, A a ):
253           F(f),
254           A(a)
255         {
256         }
257 
functor_wrapperboost::detail::function::functor_wrapper258         functor_wrapper(const functor_wrapper& f) :
259           F(static_cast<const F&>(f)),
260           A(static_cast<const A&>(f))
261         {
262         }
263       };
264 
265       /**
266        * The functor_manager class contains a static function "manage" which
267        * can clone or destroy the given function/function object pointer.
268        */
269       template<typename Functor>
270       struct functor_manager_common
271       {
272         typedef Functor functor_type;
273 
274         // Function pointers
275         static inline void
manage_ptrboost::detail::function::functor_manager_common276         manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
277                 functor_manager_operation_type op)
278         {
279           if (op == clone_functor_tag)
280             out_buffer.func_ptr = in_buffer.func_ptr;
281           else if (op == move_functor_tag) {
282             out_buffer.func_ptr = in_buffer.func_ptr;
283             in_buffer.func_ptr = 0;
284           } else if (op == destroy_functor_tag)
285             out_buffer.func_ptr = 0;
286           else if (op == check_functor_type_tag) {
287             const boost::detail::sp_typeinfo& check_type
288               = *out_buffer.type.type;
289             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
290               out_buffer.obj_ptr = &in_buffer.func_ptr;
291             else
292               out_buffer.obj_ptr = 0;
293           } else /* op == get_functor_type_tag */ {
294             out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
295             out_buffer.type.const_qualified = false;
296             out_buffer.type.volatile_qualified = false;
297           }
298         }
299 
300         // Function objects that fit in the small-object buffer.
301         static inline void
manage_smallboost::detail::function::functor_manager_common302         manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
303                 functor_manager_operation_type op)
304         {
305           if (op == clone_functor_tag || op == move_functor_tag) {
306             const functor_type* in_functor =
307               reinterpret_cast<const functor_type*>(&in_buffer.data);
308             new (reinterpret_cast<void*>(&out_buffer.data)) functor_type(*in_functor);
309 
310             if (op == move_functor_tag) {
311               functor_type* f = reinterpret_cast<functor_type*>(&in_buffer.data);
312               (void)f; // suppress warning about the value of f not being used (MSVC)
313               f->~Functor();
314             }
315           } else if (op == destroy_functor_tag) {
316             // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
317              functor_type* f = reinterpret_cast<functor_type*>(&out_buffer.data);
318              (void)f; // suppress warning about the value of f not being used (MSVC)
319              f->~Functor();
320           } else if (op == check_functor_type_tag) {
321             const detail::sp_typeinfo& check_type
322               = *out_buffer.type.type;
323             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
324               out_buffer.obj_ptr = &in_buffer.data;
325             else
326               out_buffer.obj_ptr = 0;
327           } else /* op == get_functor_type_tag */ {
328             out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
329             out_buffer.type.const_qualified = false;
330             out_buffer.type.volatile_qualified = false;
331           }
332         }
333       };
334 
335       template<typename Functor>
336       struct functor_manager
337       {
338       private:
339         typedef Functor functor_type;
340 
341         // Function pointers
342         static inline void
managerboost::detail::function::functor_manager343         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
344                 functor_manager_operation_type op, function_ptr_tag)
345         {
346           functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
347         }
348 
349         // Function objects that fit in the small-object buffer.
350         static inline void
managerboost::detail::function::functor_manager351         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
352                 functor_manager_operation_type op, mpl::true_)
353         {
354           functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
355         }
356 
357         // Function objects that require heap allocation
358         static inline void
managerboost::detail::function::functor_manager359         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
360                 functor_manager_operation_type op, mpl::false_)
361         {
362           if (op == clone_functor_tag) {
363             // Clone the functor
364             // GCC 2.95.3 gets the CV qualifiers wrong here, so we
365             // can't do the static_cast that we should do.
366             // jewillco: Changing this to static_cast because GCC 2.95.3 is
367             // obsolete.
368             const functor_type* f =
369               static_cast<const functor_type*>(in_buffer.obj_ptr);
370             functor_type* new_f = new functor_type(*f);
371             out_buffer.obj_ptr = new_f;
372           } else if (op == move_functor_tag) {
373             out_buffer.obj_ptr = in_buffer.obj_ptr;
374             in_buffer.obj_ptr = 0;
375           } else if (op == destroy_functor_tag) {
376             /* Cast from the void pointer to the functor pointer type */
377             functor_type* f =
378               static_cast<functor_type*>(out_buffer.obj_ptr);
379             delete f;
380             out_buffer.obj_ptr = 0;
381           } else if (op == check_functor_type_tag) {
382             const detail::sp_typeinfo& check_type
383               = *out_buffer.type.type;
384             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
385               out_buffer.obj_ptr = in_buffer.obj_ptr;
386             else
387               out_buffer.obj_ptr = 0;
388           } else /* op == get_functor_type_tag */ {
389             out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
390             out_buffer.type.const_qualified = false;
391             out_buffer.type.volatile_qualified = false;
392           }
393         }
394 
395         // For function objects, we determine whether the function
396         // object can use the small-object optimization buffer or
397         // whether we need to allocate it on the heap.
398         static inline void
managerboost::detail::function::functor_manager399         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
400                 functor_manager_operation_type op, function_obj_tag)
401         {
402           manager(in_buffer, out_buffer, op,
403                   mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
404         }
405 
406         // For member pointers, we use the small-object optimization buffer.
407         static inline void
managerboost::detail::function::functor_manager408         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
409                 functor_manager_operation_type op, member_ptr_tag)
410         {
411           manager(in_buffer, out_buffer, op, mpl::true_());
412         }
413 
414       public:
415         /* Dispatch to an appropriate manager based on whether we have a
416            function pointer or a function object pointer. */
417         static inline void
manageboost::detail::function::functor_manager418         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
419                functor_manager_operation_type op)
420         {
421           typedef typename get_function_tag<functor_type>::type tag_type;
422           switch (op) {
423           case get_functor_type_tag:
424             out_buffer.type.type = &BOOST_SP_TYPEID(functor_type);
425             out_buffer.type.const_qualified = false;
426             out_buffer.type.volatile_qualified = false;
427             return;
428 
429           default:
430             manager(in_buffer, out_buffer, op, tag_type());
431             return;
432           }
433         }
434       };
435 
436       template<typename Functor, typename Allocator>
437       struct functor_manager_a
438       {
439       private:
440         typedef Functor functor_type;
441 
442         // Function pointers
443         static inline void
managerboost::detail::function::functor_manager_a444         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
445                 functor_manager_operation_type op, function_ptr_tag)
446         {
447           functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
448         }
449 
450         // Function objects that fit in the small-object buffer.
451         static inline void
managerboost::detail::function::functor_manager_a452         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
453                 functor_manager_operation_type op, mpl::true_)
454         {
455           functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
456         }
457 
458         // Function objects that require heap allocation
459         static inline void
managerboost::detail::function::functor_manager_a460         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
461                 functor_manager_operation_type op, mpl::false_)
462         {
463           typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
464           typedef typename Allocator::template rebind<functor_wrapper_type>::other
465             wrapper_allocator_type;
466           typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
467 
468           if (op == clone_functor_tag) {
469             // Clone the functor
470             // GCC 2.95.3 gets the CV qualifiers wrong here, so we
471             // can't do the static_cast that we should do.
472             const functor_wrapper_type* f =
473               static_cast<const functor_wrapper_type*>(in_buffer.obj_ptr);
474             wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
475             wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
476             wrapper_allocator.construct(copy, *f);
477 
478             // Get back to the original pointer type
479             functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
480             out_buffer.obj_ptr = new_f;
481           } else if (op == move_functor_tag) {
482             out_buffer.obj_ptr = in_buffer.obj_ptr;
483             in_buffer.obj_ptr = 0;
484           } else if (op == destroy_functor_tag) {
485             /* Cast from the void pointer to the functor_wrapper_type */
486             functor_wrapper_type* victim =
487               static_cast<functor_wrapper_type*>(in_buffer.obj_ptr);
488             wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
489             wrapper_allocator.destroy(victim);
490             wrapper_allocator.deallocate(victim,1);
491             out_buffer.obj_ptr = 0;
492           } else if (op == check_functor_type_tag) {
493             const detail::sp_typeinfo& check_type
494               = *out_buffer.type.type;
495             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, BOOST_SP_TYPEID(Functor)))
496               out_buffer.obj_ptr = in_buffer.obj_ptr;
497             else
498               out_buffer.obj_ptr = 0;
499           } else /* op == get_functor_type_tag */ {
500             out_buffer.type.type = &BOOST_SP_TYPEID(Functor);
501             out_buffer.type.const_qualified = false;
502             out_buffer.type.volatile_qualified = false;
503           }
504         }
505 
506         // For function objects, we determine whether the function
507         // object can use the small-object optimization buffer or
508         // whether we need to allocate it on the heap.
509         static inline void
managerboost::detail::function::functor_manager_a510         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
511                 functor_manager_operation_type op, function_obj_tag)
512         {
513           manager(in_buffer, out_buffer, op,
514                   mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
515         }
516 
517       public:
518         /* Dispatch to an appropriate manager based on whether we have a
519            function pointer or a function object pointer. */
520         static inline void
manageboost::detail::function::functor_manager_a521         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
522                functor_manager_operation_type op)
523         {
524           typedef typename get_function_tag<functor_type>::type tag_type;
525           switch (op) {
526           case get_functor_type_tag:
527             out_buffer.type.type = &BOOST_SP_TYPEID(functor_type);
528             out_buffer.type.const_qualified = false;
529             out_buffer.type.volatile_qualified = false;
530             return;
531 
532           default:
533             manager(in_buffer, out_buffer, op, tag_type());
534             return;
535           }
536         }
537       };
538 
539       // A type that is only used for comparisons against zero
540       struct useless_clear_type {};
541 
542 #ifdef BOOST_NO_SFINAE
543       // These routines perform comparisons between a Boost.Function
544       // object and an arbitrary function object (when the last
545       // parameter is mpl::bool_<false>) or against zero (when the
546       // last parameter is mpl::bool_<true>). They are only necessary
547       // for compilers that don't support SFINAE.
548       template<typename Function, typename Functor>
549         bool
compare_equal(const Function & f,const Functor &,int,mpl::bool_<true>)550         compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
551         { return f.empty(); }
552 
553       template<typename Function, typename Functor>
554         bool
compare_not_equal(const Function & f,const Functor &,int,mpl::bool_<true>)555         compare_not_equal(const Function& f, const Functor&, int,
556                           mpl::bool_<true>)
557         { return !f.empty(); }
558 
559       template<typename Function, typename Functor>
560         bool
compare_equal(const Function & f,const Functor & g,long,mpl::bool_<false>)561         compare_equal(const Function& f, const Functor& g, long,
562                       mpl::bool_<false>)
563         {
564           if (const Functor* fp = f.template target<Functor>())
565             return function_equal(*fp, g);
566           else return false;
567         }
568 
569       template<typename Function, typename Functor>
570         bool
compare_equal(const Function & f,const reference_wrapper<Functor> & g,int,mpl::bool_<false>)571         compare_equal(const Function& f, const reference_wrapper<Functor>& g,
572                       int, mpl::bool_<false>)
573         {
574           if (const Functor* fp = f.template target<Functor>())
575             return fp == g.get_pointer();
576           else return false;
577         }
578 
579       template<typename Function, typename Functor>
580         bool
compare_not_equal(const Function & f,const Functor & g,long,mpl::bool_<false>)581         compare_not_equal(const Function& f, const Functor& g, long,
582                           mpl::bool_<false>)
583         {
584           if (const Functor* fp = f.template target<Functor>())
585             return !function_equal(*fp, g);
586           else return true;
587         }
588 
589       template<typename Function, typename Functor>
590         bool
compare_not_equal(const Function & f,const reference_wrapper<Functor> & g,int,mpl::bool_<false>)591         compare_not_equal(const Function& f,
592                           const reference_wrapper<Functor>& g, int,
593                           mpl::bool_<false>)
594         {
595           if (const Functor* fp = f.template target<Functor>())
596             return fp != g.get_pointer();
597           else return true;
598         }
599 #endif // BOOST_NO_SFINAE
600 
601       /**
602        * Stores the "manager" portion of the vtable for a
603        * boost::function object.
604        */
605       struct vtable_base
606       {
607         void (*manager)(const function_buffer& in_buffer,
608                         function_buffer& out_buffer,
609                         functor_manager_operation_type op);
610       };
611     } // end namespace function
612   } // end namespace detail
613 
614 /**
615  * The function_base class contains the basic elements needed for the
616  * function1, function2, function3, etc. classes. It is common to all
617  * functions (and as such can be used to tell if we have one of the
618  * functionN objects).
619  */
620 class function_base
621 {
622 public:
function_base()623   function_base() : vtable(0) { }
624 
625   /** Determine if the function is empty (i.e., has no target). */
empty() const626   bool empty() const { return !vtable; }
627 
628   /** Retrieve the type of the stored function object, or BOOST_SP_TYPEID(void)
629       if this is empty. */
target_type() const630   const detail::sp_typeinfo& target_type() const
631   {
632     if (!vtable) return BOOST_SP_TYPEID(void);
633 
634     detail::function::function_buffer type;
635     get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
636     return *type.type.type;
637   }
638 
639   template<typename Functor>
target()640     Functor* target()
641     {
642       if (!vtable) return 0;
643 
644       detail::function::function_buffer type_result;
645       type_result.type.type = &BOOST_SP_TYPEID(Functor);
646       type_result.type.const_qualified = is_const<Functor>::value;
647       type_result.type.volatile_qualified = is_volatile<Functor>::value;
648       get_vtable()->manager(functor, type_result,
649                       detail::function::check_functor_type_tag);
650       return static_cast<Functor*>(type_result.obj_ptr);
651     }
652 
653   template<typename Functor>
target() const654     const Functor* target() const
655     {
656       if (!vtable) return 0;
657 
658       detail::function::function_buffer type_result;
659       type_result.type.type = &BOOST_SP_TYPEID(Functor);
660       type_result.type.const_qualified = true;
661       type_result.type.volatile_qualified = is_volatile<Functor>::value;
662       get_vtable()->manager(functor, type_result,
663                       detail::function::check_functor_type_tag);
664       // GCC 2.95.3 gets the CV qualifiers wrong here, so we
665       // can't do the static_cast that we should do.
666       return static_cast<const Functor*>(type_result.obj_ptr);
667     }
668 
669   template<typename F>
contains(const F & f) const670     bool contains(const F& f) const
671     {
672       if (const F* fp = this->template target<F>())
673       {
674         return function_equal(*fp, f);
675       } else {
676         return false;
677       }
678     }
679 
680 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
681   // GCC 3.3 and newer cannot copy with the global operator==, due to
682   // problems with instantiation of function return types before it
683   // has been verified that the argument types match up.
684   template<typename Functor>
685     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
686     operator==(Functor g) const
687     {
688       if (const Functor* fp = target<Functor>())
689         return function_equal(*fp, g);
690       else return false;
691     }
692 
693   template<typename Functor>
694     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
695     operator!=(Functor g) const
696     {
697       if (const Functor* fp = target<Functor>())
698         return !function_equal(*fp, g);
699       else return true;
700     }
701 #endif
702 
703 public: // should be protected, but GCC 2.95.3 will fail to allow access
get_vtable() const704   detail::function::vtable_base* get_vtable() const {
705     return reinterpret_cast<detail::function::vtable_base*>(
706              reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
707   }
708 
has_trivial_copy_and_destroy() const709   bool has_trivial_copy_and_destroy() const {
710     return reinterpret_cast<std::size_t>(vtable) & 0x01;
711   }
712 
713   detail::function::vtable_base* vtable;
714   mutable detail::function::function_buffer functor;
715 };
716 
717 /**
718  * The bad_function_call exception class is thrown when a boost::function
719  * object is invoked
720  */
721 class bad_function_call : public std::runtime_error
722 {
723 public:
bad_function_call()724   bad_function_call() : std::runtime_error("call to empty boost::function") {}
725 };
726 
727 #ifndef BOOST_NO_SFINAE
operator ==(const function_base & f,detail::function::useless_clear_type *)728 inline bool operator==(const function_base& f,
729                        detail::function::useless_clear_type*)
730 {
731   return f.empty();
732 }
733 
operator !=(const function_base & f,detail::function::useless_clear_type *)734 inline bool operator!=(const function_base& f,
735                        detail::function::useless_clear_type*)
736 {
737   return !f.empty();
738 }
739 
operator ==(detail::function::useless_clear_type *,const function_base & f)740 inline bool operator==(detail::function::useless_clear_type*,
741                        const function_base& f)
742 {
743   return f.empty();
744 }
745 
operator !=(detail::function::useless_clear_type *,const function_base & f)746 inline bool operator!=(detail::function::useless_clear_type*,
747                        const function_base& f)
748 {
749   return !f.empty();
750 }
751 #endif
752 
753 #ifdef BOOST_NO_SFINAE
754 // Comparisons between boost::function objects and arbitrary function objects
755 template<typename Functor>
operator ==(const function_base & f,Functor g)756   inline bool operator==(const function_base& f, Functor g)
757   {
758     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
759     return detail::function::compare_equal(f, g, 0, integral());
760   }
761 
762 template<typename Functor>
operator ==(Functor g,const function_base & f)763   inline bool operator==(Functor g, const function_base& f)
764   {
765     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
766     return detail::function::compare_equal(f, g, 0, integral());
767   }
768 
769 template<typename Functor>
operator !=(const function_base & f,Functor g)770   inline bool operator!=(const function_base& f, Functor g)
771   {
772     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
773     return detail::function::compare_not_equal(f, g, 0, integral());
774   }
775 
776 template<typename Functor>
operator !=(Functor g,const function_base & f)777   inline bool operator!=(Functor g, const function_base& f)
778   {
779     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
780     return detail::function::compare_not_equal(f, g, 0, integral());
781   }
782 #else
783 
784 #  if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
785 // Comparisons between boost::function objects and arbitrary function
786 // objects. GCC 3.3 and before has an obnoxious bug that prevents this
787 // from working.
788 template<typename Functor>
789   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
790   operator==(const function_base& f, Functor g)
791   {
792     if (const Functor* fp = f.template target<Functor>())
793       return function_equal(*fp, g);
794     else return false;
795   }
796 
797 template<typename Functor>
798   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
799   operator==(Functor g, const function_base& f)
800   {
801     if (const Functor* fp = f.template target<Functor>())
802       return function_equal(g, *fp);
803     else return false;
804   }
805 
806 template<typename Functor>
807   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
808   operator!=(const function_base& f, Functor g)
809   {
810     if (const Functor* fp = f.template target<Functor>())
811       return !function_equal(*fp, g);
812     else return true;
813   }
814 
815 template<typename Functor>
816   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
817   operator!=(Functor g, const function_base& f)
818   {
819     if (const Functor* fp = f.template target<Functor>())
820       return !function_equal(g, *fp);
821     else return true;
822   }
823 #  endif
824 
825 template<typename Functor>
826   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
827   operator==(const function_base& f, reference_wrapper<Functor> g)
828   {
829     if (const Functor* fp = f.template target<Functor>())
830       return fp == g.get_pointer();
831     else return false;
832   }
833 
834 template<typename Functor>
835   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
836   operator==(reference_wrapper<Functor> g, const function_base& f)
837   {
838     if (const Functor* fp = f.template target<Functor>())
839       return g.get_pointer() == fp;
840     else return false;
841   }
842 
843 template<typename Functor>
844   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
845   operator!=(const function_base& f, reference_wrapper<Functor> g)
846   {
847     if (const Functor* fp = f.template target<Functor>())
848       return fp != g.get_pointer();
849     else return true;
850   }
851 
852 template<typename Functor>
853   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
854   operator!=(reference_wrapper<Functor> g, const function_base& f)
855   {
856     if (const Functor* fp = f.template target<Functor>())
857       return g.get_pointer() != fp;
858     else return true;
859   }
860 
861 #endif // Compiler supporting SFINAE
862 
863 namespace detail {
864   namespace function {
has_empty_target(const function_base * f)865     inline bool has_empty_target(const function_base* f)
866     {
867       return f->empty();
868     }
869 
870 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
has_empty_target(const void *)871     inline bool has_empty_target(const void*)
872     {
873       return false;
874     }
875 #else
has_empty_target(...)876     inline bool has_empty_target(...)
877     {
878       return false;
879     }
880 #endif
881   } // end namespace function
882 } // end namespace detail
883 } // end namespace boost
884 
885 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
886 #undef BOOST_FUNCTION_COMPARE_TYPE_ID
887 
888 #if defined(BOOST_MSVC)
889 #   pragma warning( pop )
890 #endif
891 
892 #endif // BOOST_FUNCTION_BASE_HEADER
893