Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:30:55

0001 // Boost.Function library
0002 
0003 //  Copyright Douglas Gregor 2001-2006
0004 //  Copyright Emil Dotchevski 2007
0005 //  Use, modification and distribution is subject to the Boost Software License, Version 1.0.
0006 //  (See accompanying file LICENSE_1_0.txt or copy at
0007 //  http://www.boost.org/LICENSE_1_0.txt)
0008 
0009 // For more information, see http://www.boost.org
0010 
0011 #ifndef BOOST_FUNCTION_BASE_HEADER
0012 #define BOOST_FUNCTION_BASE_HEADER
0013 
0014 #include <boost/function/function_fwd.hpp>
0015 #include <boost/function_equal.hpp>
0016 #include <boost/core/typeinfo.hpp>
0017 #include <boost/core/ref.hpp>
0018 #include <boost/type_traits/has_trivial_copy.hpp>
0019 #include <boost/type_traits/has_trivial_destructor.hpp>
0020 #include <boost/type_traits/is_const.hpp>
0021 #include <boost/type_traits/is_integral.hpp>
0022 #include <boost/type_traits/is_volatile.hpp>
0023 #include <boost/type_traits/composite_traits.hpp>
0024 #include <boost/type_traits/conditional.hpp>
0025 #include <boost/type_traits/alignment_of.hpp>
0026 #include <boost/type_traits/enable_if.hpp>
0027 #include <boost/type_traits/integral_constant.hpp>
0028 #include <boost/type_traits/is_function.hpp>
0029 #include <boost/assert.hpp>
0030 #include <boost/config.hpp>
0031 #include <boost/config/workaround.hpp>
0032 #include <stdexcept>
0033 #include <string>
0034 #include <memory>
0035 #include <new>
0036 
0037 #if defined(BOOST_MSVC)
0038 #   pragma warning( push )
0039 #   pragma warning( disable : 4793 ) // complaint about native code generation
0040 #   pragma warning( disable : 4127 ) // "conditional expression is constant"
0041 #endif
0042 
0043 #if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
0044 #  define BOOST_FUNCTION_TARGET_FIX(x) x
0045 #else
0046 #  define BOOST_FUNCTION_TARGET_FIX(x)
0047 #endif // __ICL etc
0048 
0049 #  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)              \
0050       typename ::boost::enable_if_<          \
0051                            !(::boost::is_integral<Functor>::value), \
0052                            Type>::type
0053 
0054 namespace boost {
0055   namespace detail {
0056     namespace function {
0057       class X;
0058 
0059       /**
0060        * A buffer used to store small function objects in
0061        * boost::function. It is a union containing function pointers,
0062        * object pointers, and a structure that resembles a bound
0063        * member function pointer.
0064        */
0065       union function_buffer_members
0066       {
0067         // For pointers to function objects
0068         typedef void* obj_ptr_t;
0069         mutable obj_ptr_t obj_ptr;
0070 
0071         // For pointers to std::type_info objects
0072         struct type_t {
0073           // (get_functor_type_tag, check_functor_type_tag).
0074           const boost::core::typeinfo* type;
0075 
0076           // Whether the type is const-qualified.
0077           bool const_qualified;
0078           // Whether the type is volatile-qualified.
0079           bool volatile_qualified;
0080         } type;
0081 
0082         // For function pointers of all kinds
0083         typedef void (*func_ptr_t)();
0084         mutable func_ptr_t func_ptr;
0085 
0086 #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
0087 # pragma warning(push)
0088 # pragma warning(disable: 5243)
0089 #endif
0090 
0091         // For bound member pointers
0092         struct bound_memfunc_ptr_t {
0093           void (X::*memfunc_ptr)(int);
0094           void* obj_ptr;
0095         } bound_memfunc_ptr;
0096 
0097 #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
0098 # pragma warning(pop)
0099 #endif
0100 
0101         // For references to function objects. We explicitly keep
0102         // track of the cv-qualifiers on the object referenced.
0103         struct obj_ref_t {
0104           mutable void* obj_ptr;
0105           bool is_const_qualified;
0106           bool is_volatile_qualified;
0107         } obj_ref;
0108       };
0109 
0110       union BOOST_SYMBOL_VISIBLE function_buffer
0111       {
0112         // Type-specific union members
0113         mutable function_buffer_members members;
0114 
0115         // To relax aliasing constraints
0116         mutable char data[sizeof(function_buffer_members)];
0117       };
0118 
0119       /**
0120        * The unusable class is a placeholder for unused function arguments
0121        * It is also completely unusable except that it constructable from
0122        * anything. This helps compilers without partial specialization to
0123        * handle Boost.Function objects returning void.
0124        */
0125       struct unusable
0126       {
0127         unusable() {}
0128         template<typename T> unusable(const T&) {}
0129       };
0130 
0131       /* Determine the return type. This supports compilers that do not support
0132        * void returns or partial specialization by silently changing the return
0133        * type to "unusable".
0134        */
0135       template<typename T> struct function_return_type { typedef T type; };
0136 
0137       template<>
0138       struct function_return_type<void>
0139       {
0140         typedef unusable type;
0141       };
0142 
0143       // The operation type to perform on the given functor/function pointer
0144       enum functor_manager_operation_type {
0145         clone_functor_tag,
0146         move_functor_tag,
0147         destroy_functor_tag,
0148         check_functor_type_tag,
0149         get_functor_type_tag
0150       };
0151 
0152       // Tags used to decide between different types of functions
0153       struct function_ptr_tag {};
0154       struct function_obj_tag {};
0155       struct member_ptr_tag {};
0156       struct function_obj_ref_tag {};
0157 
0158       template<typename F>
0159       class get_function_tag
0160       {
0161         typedef typename conditional<(is_pointer<F>::value),
0162                                    function_ptr_tag,
0163                                    function_obj_tag>::type ptr_or_obj_tag;
0164 
0165         typedef typename conditional<(is_member_pointer<F>::value),
0166                                    member_ptr_tag,
0167                                    ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
0168 
0169         typedef typename conditional<(is_reference_wrapper<F>::value),
0170                                    function_obj_ref_tag,
0171                                    ptr_or_obj_or_mem_tag>::type or_ref_tag;
0172 
0173       public:
0174         typedef or_ref_tag type;
0175       };
0176 
0177       // The trivial manager does nothing but return the same pointer (if we
0178       // are cloning) or return the null pointer (if we are deleting).
0179       template<typename F>
0180       struct reference_manager
0181       {
0182         static inline void
0183         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0184                functor_manager_operation_type op)
0185         {
0186           switch (op) {
0187           case clone_functor_tag:
0188             out_buffer.members.obj_ref = in_buffer.members.obj_ref;
0189             return;
0190 
0191           case move_functor_tag:
0192             out_buffer.members.obj_ref = in_buffer.members.obj_ref;
0193             in_buffer.members.obj_ref.obj_ptr = 0;
0194             return;
0195 
0196           case destroy_functor_tag:
0197             out_buffer.members.obj_ref.obj_ptr = 0;
0198             return;
0199 
0200           case check_functor_type_tag:
0201             {
0202               // Check whether we have the same type. We can add
0203               // cv-qualifiers, but we can't take them away.
0204               if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(F)
0205                   && (!in_buffer.members.obj_ref.is_const_qualified
0206                       || out_buffer.members.type.const_qualified)
0207                   && (!in_buffer.members.obj_ref.is_volatile_qualified
0208                       || out_buffer.members.type.volatile_qualified))
0209                 out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
0210               else
0211                 out_buffer.members.obj_ptr = 0;
0212             }
0213             return;
0214 
0215           case get_functor_type_tag:
0216             out_buffer.members.type.type = &BOOST_CORE_TYPEID(F);
0217             out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
0218             out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
0219             return;
0220           }
0221         }
0222       };
0223 
0224       /**
0225        * Determine if boost::function can use the small-object
0226        * optimization with the function object type F.
0227        */
0228       template<typename F>
0229       struct function_allows_small_object_optimization
0230       {
0231         BOOST_STATIC_CONSTANT
0232           (bool,
0233            value = ((sizeof(F) <= sizeof(function_buffer) &&
0234                      (alignment_of<function_buffer>::value
0235                       % alignment_of<F>::value == 0))));
0236       };
0237 
0238       template <typename F,typename A>
0239       struct functor_wrapper: public F, public A
0240       {
0241         functor_wrapper( F f, A a ):
0242           F(f),
0243           A(a)
0244         {
0245         }
0246 
0247         functor_wrapper(const functor_wrapper& f) :
0248           F(static_cast<const F&>(f)),
0249           A(static_cast<const A&>(f))
0250         {
0251         }
0252       };
0253 
0254       /**
0255        * The functor_manager class contains a static function "manage" which
0256        * can clone or destroy the given function/function object pointer.
0257        */
0258       template<typename Functor>
0259       struct functor_manager_common
0260       {
0261         typedef Functor functor_type;
0262 
0263         // Function pointers
0264         static inline void
0265         manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
0266                 functor_manager_operation_type op)
0267         {
0268           if (op == clone_functor_tag)
0269             out_buffer.members.func_ptr = in_buffer.members.func_ptr;
0270           else if (op == move_functor_tag) {
0271             out_buffer.members.func_ptr = in_buffer.members.func_ptr;
0272             in_buffer.members.func_ptr = 0;
0273           } else if (op == destroy_functor_tag)
0274             out_buffer.members.func_ptr = 0;
0275           else if (op == check_functor_type_tag) {
0276             if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0277               out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
0278             else
0279               out_buffer.members.obj_ptr = 0;
0280           } else /* op == get_functor_type_tag */ {
0281             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0282             out_buffer.members.type.const_qualified = false;
0283             out_buffer.members.type.volatile_qualified = false;
0284           }
0285         }
0286 
0287         // Function objects that fit in the small-object buffer.
0288         static inline void
0289         manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
0290                 functor_manager_operation_type op)
0291         {
0292           if (op == clone_functor_tag || op == move_functor_tag) {
0293             const functor_type* in_functor =
0294               reinterpret_cast<const functor_type*>(in_buffer.data);
0295             new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
0296 
0297             if (op == move_functor_tag) {
0298               functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
0299               (void)f; // suppress warning about the value of f not being used (MSVC)
0300               f->~Functor();
0301             }
0302           } else if (op == destroy_functor_tag) {
0303             // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
0304              functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data);
0305              (void)f; // suppress warning about the value of f not being used (MSVC)
0306              f->~Functor();
0307           } else if (op == check_functor_type_tag) {
0308              if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0309               out_buffer.members.obj_ptr = in_buffer.data;
0310             else
0311               out_buffer.members.obj_ptr = 0;
0312           } else /* op == get_functor_type_tag */ {
0313             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0314             out_buffer.members.type.const_qualified = false;
0315             out_buffer.members.type.volatile_qualified = false;
0316           }
0317         }
0318       };
0319 
0320       template<typename Functor>
0321       struct functor_manager
0322       {
0323       private:
0324         typedef Functor functor_type;
0325 
0326         // Function pointers
0327         static inline void
0328         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0329                 functor_manager_operation_type op, function_ptr_tag)
0330         {
0331           functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
0332         }
0333 
0334         // Function objects that fit in the small-object buffer.
0335         static inline void
0336         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0337                 functor_manager_operation_type op, true_type)
0338         {
0339           functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
0340         }
0341 
0342         // Function objects that require heap allocation
0343         static inline void
0344         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0345                 functor_manager_operation_type op, false_type)
0346         {
0347           if (op == clone_functor_tag) {
0348             // Clone the functor
0349             // GCC 2.95.3 gets the CV qualifiers wrong here, so we
0350             // can't do the static_cast that we should do.
0351             // jewillco: Changing this to static_cast because GCC 2.95.3 is
0352             // obsolete.
0353             const functor_type* f =
0354               static_cast<const functor_type*>(in_buffer.members.obj_ptr);
0355             functor_type* new_f = new functor_type(*f);
0356             out_buffer.members.obj_ptr = new_f;
0357           } else if (op == move_functor_tag) {
0358             out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0359             in_buffer.members.obj_ptr = 0;
0360           } else if (op == destroy_functor_tag) {
0361             /* Cast from the void pointer to the functor pointer type */
0362             functor_type* f =
0363               static_cast<functor_type*>(out_buffer.members.obj_ptr);
0364             delete f;
0365             out_buffer.members.obj_ptr = 0;
0366           } else if (op == check_functor_type_tag) {
0367             if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0368               out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0369             else
0370               out_buffer.members.obj_ptr = 0;
0371           } else /* op == get_functor_type_tag */ {
0372             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0373             out_buffer.members.type.const_qualified = false;
0374             out_buffer.members.type.volatile_qualified = false;
0375           }
0376         }
0377 
0378         // For function objects, we determine whether the function
0379         // object can use the small-object optimization buffer or
0380         // whether we need to allocate it on the heap.
0381         static inline void
0382         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0383                 functor_manager_operation_type op, function_obj_tag)
0384         {
0385           manager(in_buffer, out_buffer, op,
0386                   integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
0387         }
0388 
0389         // For member pointers, we use the small-object optimization buffer.
0390         static inline void
0391         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0392                 functor_manager_operation_type op, member_ptr_tag)
0393         {
0394           manager(in_buffer, out_buffer, op, true_type());
0395         }
0396 
0397       public:
0398         /* Dispatch to an appropriate manager based on whether we have a
0399            function pointer or a function object pointer. */
0400         static inline void
0401         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0402                functor_manager_operation_type op)
0403         {
0404           typedef typename get_function_tag<functor_type>::type tag_type;
0405           if (op == get_functor_type_tag) {
0406             out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
0407             out_buffer.members.type.const_qualified = false;
0408             out_buffer.members.type.volatile_qualified = false;
0409           } else {
0410             manager(in_buffer, out_buffer, op, tag_type());
0411           }
0412         }
0413       };
0414 
0415       template<typename Functor, typename Allocator>
0416       struct functor_manager_a
0417       {
0418       private:
0419         typedef Functor functor_type;
0420 
0421         // Function pointers
0422         static inline void
0423         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0424                 functor_manager_operation_type op, function_ptr_tag)
0425         {
0426           functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
0427         }
0428 
0429         // Function objects that fit in the small-object buffer.
0430         static inline void
0431         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0432                 functor_manager_operation_type op, true_type)
0433         {
0434           functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
0435         }
0436 
0437         // Function objects that require heap allocation
0438         static inline void
0439         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0440                 functor_manager_operation_type op, false_type)
0441         {
0442           typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
0443 #if defined(BOOST_NO_CXX11_ALLOCATOR)
0444           typedef typename Allocator::template rebind<functor_wrapper_type>::other
0445             wrapper_allocator_type;
0446           typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_type;
0447 #else
0448           using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
0449           using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
0450 #endif
0451 
0452           if (op == clone_functor_tag) {
0453             // Clone the functor
0454             // GCC 2.95.3 gets the CV qualifiers wrong here, so we
0455             // can't do the static_cast that we should do.
0456             const functor_wrapper_type* f =
0457               static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
0458             wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
0459             wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
0460 #if defined(BOOST_NO_CXX11_ALLOCATOR)
0461             wrapper_allocator.construct(copy, *f);
0462 #else
0463             std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, *f);
0464 #endif
0465 
0466             // Get back to the original pointer type
0467             functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
0468             out_buffer.members.obj_ptr = new_f;
0469           } else if (op == move_functor_tag) {
0470             out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0471             in_buffer.members.obj_ptr = 0;
0472           } else if (op == destroy_functor_tag) {
0473             /* Cast from the void pointer to the functor_wrapper_type */
0474             functor_wrapper_type* victim =
0475               static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
0476             wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
0477 #if defined(BOOST_NO_CXX11_ALLOCATOR)
0478             wrapper_allocator.destroy(victim);
0479 #else
0480             std::allocator_traits<wrapper_allocator_type>::destroy(wrapper_allocator, victim);
0481 #endif
0482             wrapper_allocator.deallocate(victim,1);
0483             out_buffer.members.obj_ptr = 0;
0484           } else if (op == check_functor_type_tag) {
0485             if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0486               out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0487             else
0488               out_buffer.members.obj_ptr = 0;
0489           } else /* op == get_functor_type_tag */ {
0490             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0491             out_buffer.members.type.const_qualified = false;
0492             out_buffer.members.type.volatile_qualified = false;
0493           }
0494         }
0495 
0496         // For function objects, we determine whether the function
0497         // object can use the small-object optimization buffer or
0498         // whether we need to allocate it on the heap.
0499         static inline void
0500         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0501                 functor_manager_operation_type op, function_obj_tag)
0502         {
0503           manager(in_buffer, out_buffer, op,
0504                   integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
0505         }
0506 
0507       public:
0508         /* Dispatch to an appropriate manager based on whether we have a
0509            function pointer or a function object pointer. */
0510         static inline void
0511         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0512                functor_manager_operation_type op)
0513         {
0514           typedef typename get_function_tag<functor_type>::type tag_type;
0515           if (op == get_functor_type_tag) {
0516             out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
0517             out_buffer.members.type.const_qualified = false;
0518             out_buffer.members.type.volatile_qualified = false;
0519           } else {
0520             manager(in_buffer, out_buffer, op, tag_type());
0521           }
0522         }
0523       };
0524 
0525       // A type that is only used for comparisons against zero
0526       struct useless_clear_type {};
0527 
0528 #ifdef BOOST_NO_SFINAE
0529       // These routines perform comparisons between a Boost.Function
0530       // object and an arbitrary function object (when the last
0531       // parameter is false_type) or against zero (when the
0532       // last parameter is true_type). They are only necessary
0533       // for compilers that don't support SFINAE.
0534       template<typename Function, typename Functor>
0535         bool
0536         compare_equal(const Function& f, const Functor&, int, true_type)
0537         { return f.empty(); }
0538 
0539       template<typename Function, typename Functor>
0540         bool
0541         compare_not_equal(const Function& f, const Functor&, int,
0542                           true_type)
0543         { return !f.empty(); }
0544 
0545       template<typename Function, typename Functor>
0546         bool
0547         compare_equal(const Function& f, const Functor& g, long,
0548                       false_type)
0549         {
0550           if (const Functor* fp = f.template target<Functor>())
0551             return function_equal(*fp, g);
0552           else return false;
0553         }
0554 
0555       template<typename Function, typename Functor>
0556         bool
0557         compare_equal(const Function& f, const reference_wrapper<Functor>& g,
0558                       int, false_type)
0559         {
0560           if (const Functor* fp = f.template target<Functor>())
0561             return fp == g.get_pointer();
0562           else return false;
0563         }
0564 
0565       template<typename Function, typename Functor>
0566         bool
0567         compare_not_equal(const Function& f, const Functor& g, long,
0568                           false_type)
0569         {
0570           if (const Functor* fp = f.template target<Functor>())
0571             return !function_equal(*fp, g);
0572           else return true;
0573         }
0574 
0575       template<typename Function, typename Functor>
0576         bool
0577         compare_not_equal(const Function& f,
0578                           const reference_wrapper<Functor>& g, int,
0579                           false_type)
0580         {
0581           if (const Functor* fp = f.template target<Functor>())
0582             return fp != g.get_pointer();
0583           else return true;
0584         }
0585 #endif // BOOST_NO_SFINAE
0586 
0587       /**
0588        * Stores the "manager" portion of the vtable for a
0589        * boost::function object.
0590        */
0591       struct vtable_base
0592       {
0593         void (*manager)(const function_buffer& in_buffer,
0594                         function_buffer& out_buffer,
0595                         functor_manager_operation_type op);
0596       };
0597     } // end namespace function
0598   } // end namespace detail
0599 
0600 /**
0601  * The function_base class contains the basic elements needed for the
0602  * function1, function2, function3, etc. classes. It is common to all
0603  * functions (and as such can be used to tell if we have one of the
0604  * functionN objects).
0605  */
0606 class function_base
0607 {
0608 public:
0609   function_base() : vtable(0) { }
0610 
0611   /** Determine if the function is empty (i.e., has no target). */
0612   bool empty() const { return !vtable; }
0613 
0614   /** Retrieve the type of the stored function object, or type_id<void>()
0615       if this is empty. */
0616   const boost::core::typeinfo& target_type() const
0617   {
0618     if (!vtable) return BOOST_CORE_TYPEID(void);
0619 
0620     detail::function::function_buffer type;
0621     get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
0622     return *type.members.type.type;
0623   }
0624 
0625   template<typename Functor>
0626     Functor* target()
0627     {
0628       if (!vtable) return 0;
0629 
0630       detail::function::function_buffer type_result;
0631       type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
0632       type_result.members.type.const_qualified = is_const<Functor>::value;
0633       type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
0634       get_vtable()->manager(functor, type_result,
0635                       detail::function::check_functor_type_tag);
0636       return static_cast<Functor*>(type_result.members.obj_ptr);
0637     }
0638 
0639   template<typename Functor>
0640     const Functor* target() const
0641     {
0642       if (!vtable) return 0;
0643 
0644       detail::function::function_buffer type_result;
0645       type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
0646       type_result.members.type.const_qualified = true;
0647       type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
0648       get_vtable()->manager(functor, type_result,
0649                       detail::function::check_functor_type_tag);
0650       // GCC 2.95.3 gets the CV qualifiers wrong here, so we
0651       // can't do the static_cast that we should do.
0652       return static_cast<const Functor*>(type_result.members.obj_ptr);
0653     }
0654 
0655   template<typename F>
0656     typename boost::enable_if_< !boost::is_function<F>::value, bool >::type
0657     contains(const F& f) const
0658     {
0659       if (const F* fp = this->template target<F>())
0660       {
0661         return function_equal(*fp, f);
0662       } else {
0663         return false;
0664       }
0665     }
0666 
0667   template<typename Fn>
0668     typename boost::enable_if_< boost::is_function<Fn>::value, bool >::type
0669     contains(Fn& f) const
0670     {
0671       typedef Fn* F;
0672       if (const F* fp = this->template target<F>())
0673       {
0674         return function_equal(*fp, &f);
0675       } else {
0676         return false;
0677       }
0678     }
0679 
0680 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
0681   // GCC 3.3 and newer cannot copy with the global operator==, due to
0682   // problems with instantiation of function return types before it
0683   // has been verified that the argument types match up.
0684   template<typename Functor>
0685     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0686     operator==(Functor g) const
0687     {
0688       if (const Functor* fp = target<Functor>())
0689         return function_equal(*fp, g);
0690       else return false;
0691     }
0692 
0693   template<typename Functor>
0694     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0695     operator!=(Functor g) const
0696     {
0697       if (const Functor* fp = target<Functor>())
0698         return !function_equal(*fp, g);
0699       else return true;
0700     }
0701 #endif
0702 
0703 public: // should be protected, but GCC 2.95.3 will fail to allow access
0704   detail::function::vtable_base* get_vtable() const {
0705     return reinterpret_cast<detail::function::vtable_base*>(
0706              reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
0707   }
0708 
0709   bool has_trivial_copy_and_destroy() const {
0710     return reinterpret_cast<std::size_t>(vtable) & 0x01;
0711   }
0712 
0713   detail::function::vtable_base* vtable;
0714   mutable detail::function::function_buffer functor;
0715 };
0716 
0717 #if defined(BOOST_CLANG)
0718 #   pragma clang diagnostic push
0719 #   pragma clang diagnostic ignored "-Wweak-vtables"
0720 #endif
0721 /**
0722  * The bad_function_call exception class is thrown when a boost::function
0723  * object is invoked
0724  */
0725 class BOOST_SYMBOL_VISIBLE bad_function_call : public std::runtime_error
0726 {
0727 public:
0728   bad_function_call() : std::runtime_error("call to empty boost::function") {}
0729 };
0730 #if defined(BOOST_CLANG)
0731 #   pragma clang diagnostic pop
0732 #endif
0733 
0734 #ifndef BOOST_NO_SFINAE
0735 inline bool operator==(const function_base& f,
0736                        detail::function::useless_clear_type*)
0737 {
0738   return f.empty();
0739 }
0740 
0741 inline bool operator!=(const function_base& f,
0742                        detail::function::useless_clear_type*)
0743 {
0744   return !f.empty();
0745 }
0746 
0747 inline bool operator==(detail::function::useless_clear_type*,
0748                        const function_base& f)
0749 {
0750   return f.empty();
0751 }
0752 
0753 inline bool operator!=(detail::function::useless_clear_type*,
0754                        const function_base& f)
0755 {
0756   return !f.empty();
0757 }
0758 #endif
0759 
0760 #ifdef BOOST_NO_SFINAE
0761 // Comparisons between boost::function objects and arbitrary function objects
0762 template<typename Functor>
0763   inline bool operator==(const function_base& f, Functor g)
0764   {
0765     typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
0766     return detail::function::compare_equal(f, g, 0, integral());
0767   }
0768 
0769 template<typename Functor>
0770   inline bool operator==(Functor g, const function_base& f)
0771   {
0772     typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
0773     return detail::function::compare_equal(f, g, 0, integral());
0774   }
0775 
0776 template<typename Functor>
0777   inline bool operator!=(const function_base& f, Functor g)
0778   {
0779     typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
0780     return detail::function::compare_not_equal(f, g, 0, integral());
0781   }
0782 
0783 template<typename Functor>
0784   inline bool operator!=(Functor g, const function_base& f)
0785   {
0786     typedef integral_constant<bool, (is_integral<Functor>::value)> integral;
0787     return detail::function::compare_not_equal(f, g, 0, integral());
0788   }
0789 #else
0790 
0791 #  if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
0792 // Comparisons between boost::function objects and arbitrary function
0793 // objects. GCC 3.3 and before has an obnoxious bug that prevents this
0794 // from working.
0795 template<typename Functor>
0796   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0797   operator==(const function_base& f, Functor g)
0798   {
0799     if (const Functor* fp = f.template target<Functor>())
0800       return function_equal(*fp, g);
0801     else return false;
0802   }
0803 
0804 template<typename Functor>
0805   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0806   operator==(Functor g, const function_base& f)
0807   {
0808     if (const Functor* fp = f.template target<Functor>())
0809       return function_equal(g, *fp);
0810     else return false;
0811   }
0812 
0813 template<typename Functor>
0814   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0815   operator!=(const function_base& f, Functor g)
0816   {
0817     if (const Functor* fp = f.template target<Functor>())
0818       return !function_equal(*fp, g);
0819     else return true;
0820   }
0821 
0822 template<typename Functor>
0823   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0824   operator!=(Functor g, const function_base& f)
0825   {
0826     if (const Functor* fp = f.template target<Functor>())
0827       return !function_equal(g, *fp);
0828     else return true;
0829   }
0830 #  endif
0831 
0832 template<typename Functor>
0833   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0834   operator==(const function_base& f, reference_wrapper<Functor> g)
0835   {
0836     if (const Functor* fp = f.template target<Functor>())
0837       return fp == g.get_pointer();
0838     else return false;
0839   }
0840 
0841 template<typename Functor>
0842   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0843   operator==(reference_wrapper<Functor> g, const function_base& f)
0844   {
0845     if (const Functor* fp = f.template target<Functor>())
0846       return g.get_pointer() == fp;
0847     else return false;
0848   }
0849 
0850 template<typename Functor>
0851   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0852   operator!=(const function_base& f, reference_wrapper<Functor> g)
0853   {
0854     if (const Functor* fp = f.template target<Functor>())
0855       return fp != g.get_pointer();
0856     else return true;
0857   }
0858 
0859 template<typename Functor>
0860   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0861   operator!=(reference_wrapper<Functor> g, const function_base& f)
0862   {
0863     if (const Functor* fp = f.template target<Functor>())
0864       return g.get_pointer() != fp;
0865     else return true;
0866   }
0867 
0868 #endif // Compiler supporting SFINAE
0869 
0870 namespace detail {
0871   namespace function {
0872     inline bool has_empty_target(const function_base* f)
0873     {
0874       return f->empty();
0875     }
0876 
0877 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
0878     inline bool has_empty_target(const void*)
0879     {
0880       return false;
0881     }
0882 #else
0883     inline bool has_empty_target(...)
0884     {
0885       return false;
0886     }
0887 #endif
0888   } // end namespace function
0889 } // end namespace detail
0890 } // end namespace boost
0891 
0892 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
0893 
0894 #if defined(BOOST_MSVC)
0895 #   pragma warning( pop )
0896 #endif
0897 
0898 #endif // BOOST_FUNCTION_BASE_HEADER