Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-11 08:07:11

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/assert.hpp>
0019 #include <boost/config.hpp>
0020 #include <boost/config/workaround.hpp>
0021 #include <stdexcept>
0022 #include <string>
0023 #include <memory>
0024 #include <new>
0025 #include <type_traits>
0026 
0027 #if defined(BOOST_MSVC)
0028 #   pragma warning( push )
0029 #   pragma warning( disable : 4793 ) // complaint about native code generation
0030 #   pragma warning( disable : 4127 ) // "conditional expression is constant"
0031 #endif
0032 
0033 // retained because used in a test
0034 #define BOOST_FUNCTION_TARGET_FIX(x)
0035 
0036 #define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
0037   typename std::enable_if< !std::is_integral<Functor>::value, Type>::type
0038 
0039 namespace boost {
0040   namespace detail {
0041     namespace function {
0042       class X;
0043 
0044       /**
0045        * A buffer used to store small function objects in
0046        * boost::function. It is a union containing function pointers,
0047        * object pointers, and a structure that resembles a bound
0048        * member function pointer.
0049        */
0050       union function_buffer_members
0051       {
0052         // For pointers to function objects
0053         typedef void* obj_ptr_t;
0054         mutable obj_ptr_t obj_ptr;
0055 
0056         // For pointers to std::type_info objects
0057         struct type_t {
0058           // (get_functor_type_tag, check_functor_type_tag).
0059           const boost::core::typeinfo* type;
0060 
0061           // Whether the type is const-qualified.
0062           bool const_qualified;
0063           // Whether the type is volatile-qualified.
0064           bool volatile_qualified;
0065         } type;
0066 
0067         // For function pointers of all kinds
0068         typedef void (*func_ptr_t)();
0069         mutable func_ptr_t func_ptr;
0070 
0071 #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
0072 # pragma warning(push)
0073 # pragma warning(disable: 5243)
0074 #endif
0075 
0076         // For bound member pointers
0077         struct bound_memfunc_ptr_t {
0078           void (X::*memfunc_ptr)(int);
0079           void* obj_ptr;
0080         } bound_memfunc_ptr;
0081 
0082 #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
0083 # pragma warning(pop)
0084 #endif
0085 
0086         // For references to function objects. We explicitly keep
0087         // track of the cv-qualifiers on the object referenced.
0088         struct obj_ref_t {
0089           mutable void* obj_ptr;
0090           bool is_const_qualified;
0091           bool is_volatile_qualified;
0092         } obj_ref;
0093       };
0094 
0095       union BOOST_SYMBOL_VISIBLE function_buffer
0096       {
0097         // Type-specific union members
0098         mutable function_buffer_members members;
0099 
0100         // To relax aliasing constraints
0101         mutable char data[sizeof(function_buffer_members)];
0102       };
0103 
0104       // The operation type to perform on the given functor/function pointer
0105       enum functor_manager_operation_type {
0106         clone_functor_tag,
0107         move_functor_tag,
0108         destroy_functor_tag,
0109         check_functor_type_tag,
0110         get_functor_type_tag
0111       };
0112 
0113       // Tags used to decide between different types of functions
0114       struct function_ptr_tag {};
0115       struct function_obj_tag {};
0116       struct member_ptr_tag {};
0117       struct function_obj_ref_tag {};
0118 
0119       template<typename F>
0120       class get_function_tag
0121       {
0122         typedef typename std::conditional<std::is_pointer<F>::value,
0123                                    function_ptr_tag,
0124                                    function_obj_tag>::type ptr_or_obj_tag;
0125 
0126         typedef typename std::conditional<std::is_member_pointer<F>::value,
0127                                    member_ptr_tag,
0128                                    ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
0129 
0130         typedef typename std::conditional<is_reference_wrapper<F>::value,
0131                                    function_obj_ref_tag,
0132                                    ptr_or_obj_or_mem_tag>::type or_ref_tag;
0133 
0134       public:
0135         typedef or_ref_tag type;
0136       };
0137 
0138       // The trivial manager does nothing but return the same pointer (if we
0139       // are cloning) or return the null pointer (if we are deleting).
0140       template<typename F>
0141       struct reference_manager
0142       {
0143         static inline void
0144         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0145                functor_manager_operation_type op)
0146         {
0147           switch (op) {
0148           case clone_functor_tag:
0149             out_buffer.members.obj_ref = in_buffer.members.obj_ref;
0150             return;
0151 
0152           case move_functor_tag:
0153             out_buffer.members.obj_ref = in_buffer.members.obj_ref;
0154             in_buffer.members.obj_ref.obj_ptr = 0;
0155             return;
0156 
0157           case destroy_functor_tag:
0158             out_buffer.members.obj_ref.obj_ptr = 0;
0159             return;
0160 
0161           case check_functor_type_tag:
0162             {
0163               // Check whether we have the same type. We can add
0164               // cv-qualifiers, but we can't take them away.
0165               if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(F)
0166                   && (!in_buffer.members.obj_ref.is_const_qualified
0167                       || out_buffer.members.type.const_qualified)
0168                   && (!in_buffer.members.obj_ref.is_volatile_qualified
0169                       || out_buffer.members.type.volatile_qualified))
0170                 out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
0171               else
0172                 out_buffer.members.obj_ptr = 0;
0173             }
0174             return;
0175 
0176           case get_functor_type_tag:
0177             out_buffer.members.type.type = &BOOST_CORE_TYPEID(F);
0178             out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
0179             out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
0180             return;
0181           }
0182         }
0183       };
0184 
0185       /**
0186        * Determine if boost::function can use the small-object
0187        * optimization with the function object type F.
0188        */
0189       template<typename F>
0190       struct function_allows_small_object_optimization
0191       {
0192         BOOST_STATIC_CONSTANT
0193           (bool,
0194            value = ((sizeof(F) <= sizeof(function_buffer) &&
0195                      (std::alignment_of<function_buffer>::value
0196                       % std::alignment_of<F>::value == 0))));
0197       };
0198 
0199       template <typename F,typename A>
0200       struct functor_wrapper: public F, public A
0201       {
0202         functor_wrapper( F f, A a ):
0203           F(f),
0204           A(a)
0205         {
0206         }
0207 
0208         functor_wrapper(const functor_wrapper& f) :
0209           F(static_cast<const F&>(f)),
0210           A(static_cast<const A&>(f))
0211         {
0212         }
0213       };
0214 
0215       /**
0216        * The functor_manager class contains a static function "manage" which
0217        * can clone or destroy the given function/function object pointer.
0218        */
0219       template<typename Functor>
0220       struct functor_manager_common
0221       {
0222         typedef Functor functor_type;
0223 
0224         // Function pointers
0225         static inline void
0226         manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
0227                 functor_manager_operation_type op)
0228         {
0229           if (op == clone_functor_tag)
0230             out_buffer.members.func_ptr = in_buffer.members.func_ptr;
0231           else if (op == move_functor_tag) {
0232             out_buffer.members.func_ptr = in_buffer.members.func_ptr;
0233             in_buffer.members.func_ptr = 0;
0234           } else if (op == destroy_functor_tag)
0235             out_buffer.members.func_ptr = 0;
0236           else if (op == check_functor_type_tag) {
0237             if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0238               out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
0239             else
0240               out_buffer.members.obj_ptr = 0;
0241           } else /* op == get_functor_type_tag */ {
0242             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0243             out_buffer.members.type.const_qualified = false;
0244             out_buffer.members.type.volatile_qualified = false;
0245           }
0246         }
0247 
0248         // Function objects that fit in the small-object buffer.
0249         static inline void
0250         manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
0251                 functor_manager_operation_type op)
0252         {
0253           if (op == clone_functor_tag) {
0254             const functor_type* in_functor =
0255               reinterpret_cast<const functor_type*>(in_buffer.data);
0256             new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
0257 
0258           } else if (op == move_functor_tag) {
0259               functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
0260               new (reinterpret_cast<void*>(out_buffer.data)) functor_type(std::move(*f));
0261               f->~Functor();
0262           } else if (op == destroy_functor_tag) {
0263             // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
0264              functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data);
0265              (void)f; // suppress warning about the value of f not being used (MSVC)
0266              f->~Functor();
0267           } else if (op == check_functor_type_tag) {
0268              if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0269               out_buffer.members.obj_ptr = in_buffer.data;
0270             else
0271               out_buffer.members.obj_ptr = 0;
0272           } else /* op == get_functor_type_tag */ {
0273             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0274             out_buffer.members.type.const_qualified = false;
0275             out_buffer.members.type.volatile_qualified = false;
0276           }
0277         }
0278       };
0279 
0280       template<typename Functor>
0281       struct functor_manager
0282       {
0283       private:
0284         typedef Functor functor_type;
0285 
0286         // Function pointers
0287         static inline void
0288         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0289                 functor_manager_operation_type op, function_ptr_tag)
0290         {
0291           functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
0292         }
0293 
0294         // Function objects that fit in the small-object buffer.
0295         static inline void
0296         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0297                 functor_manager_operation_type op, std::true_type)
0298         {
0299           functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
0300         }
0301 
0302         // Function objects that require heap allocation
0303         static inline void
0304         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0305                 functor_manager_operation_type op, std::false_type)
0306         {
0307           if (op == clone_functor_tag) {
0308             // Clone the functor
0309             // GCC 2.95.3 gets the CV qualifiers wrong here, so we
0310             // can't do the static_cast that we should do.
0311             // jewillco: Changing this to static_cast because GCC 2.95.3 is
0312             // obsolete.
0313             const functor_type* f =
0314               static_cast<const functor_type*>(in_buffer.members.obj_ptr);
0315             functor_type* new_f = new functor_type(*f);
0316             out_buffer.members.obj_ptr = new_f;
0317           } else if (op == move_functor_tag) {
0318             out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0319             in_buffer.members.obj_ptr = 0;
0320           } else if (op == destroy_functor_tag) {
0321             /* Cast from the void pointer to the functor pointer type */
0322             functor_type* f =
0323               static_cast<functor_type*>(out_buffer.members.obj_ptr);
0324             delete f;
0325             out_buffer.members.obj_ptr = 0;
0326           } else if (op == check_functor_type_tag) {
0327             if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0328               out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0329             else
0330               out_buffer.members.obj_ptr = 0;
0331           } else /* op == get_functor_type_tag */ {
0332             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0333             out_buffer.members.type.const_qualified = false;
0334             out_buffer.members.type.volatile_qualified = false;
0335           }
0336         }
0337 
0338         // For function objects, we determine whether the function
0339         // object can use the small-object optimization buffer or
0340         // whether we need to allocate it on the heap.
0341         static inline void
0342         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0343                 functor_manager_operation_type op, function_obj_tag)
0344         {
0345           manager(in_buffer, out_buffer, op,
0346                   std::integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
0347         }
0348 
0349         // For member pointers, we use the small-object optimization buffer.
0350         static inline void
0351         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0352                 functor_manager_operation_type op, member_ptr_tag)
0353         {
0354           manager(in_buffer, out_buffer, op, std::true_type());
0355         }
0356 
0357       public:
0358         /* Dispatch to an appropriate manager based on whether we have a
0359            function pointer or a function object pointer. */
0360         static inline void
0361         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0362                functor_manager_operation_type op)
0363         {
0364           typedef typename get_function_tag<functor_type>::type tag_type;
0365           if (op == get_functor_type_tag) {
0366             out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
0367             out_buffer.members.type.const_qualified = false;
0368             out_buffer.members.type.volatile_qualified = false;
0369           } else {
0370             manager(in_buffer, out_buffer, op, tag_type());
0371           }
0372         }
0373       };
0374 
0375       template<typename Functor, typename Allocator>
0376       struct functor_manager_a
0377       {
0378       private:
0379         typedef Functor functor_type;
0380 
0381         // Function pointers
0382         static inline void
0383         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0384                 functor_manager_operation_type op, function_ptr_tag)
0385         {
0386           functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
0387         }
0388 
0389         // Function objects that fit in the small-object buffer.
0390         static inline void
0391         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0392                 functor_manager_operation_type op, std::true_type)
0393         {
0394           functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
0395         }
0396 
0397         // Function objects that require heap allocation
0398         static inline void
0399         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0400                 functor_manager_operation_type op, std::false_type)
0401         {
0402           typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
0403 
0404           using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
0405           using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
0406 
0407           if (op == clone_functor_tag) {
0408             // Clone the functor
0409             // GCC 2.95.3 gets the CV qualifiers wrong here, so we
0410             // can't do the static_cast that we should do.
0411             const functor_wrapper_type* f =
0412               static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
0413             wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
0414             wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
0415             std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, *f);
0416 
0417             // Get back to the original pointer type
0418             functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
0419             out_buffer.members.obj_ptr = new_f;
0420           } else if (op == move_functor_tag) {
0421             out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0422             in_buffer.members.obj_ptr = 0;
0423           } else if (op == destroy_functor_tag) {
0424             /* Cast from the void pointer to the functor_wrapper_type */
0425             functor_wrapper_type* victim =
0426               static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
0427             wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
0428             std::allocator_traits<wrapper_allocator_type>::destroy(wrapper_allocator, victim);
0429             wrapper_allocator.deallocate(victim,1);
0430             out_buffer.members.obj_ptr = 0;
0431           } else if (op == check_functor_type_tag) {
0432             if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
0433               out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
0434             else
0435               out_buffer.members.obj_ptr = 0;
0436           } else /* op == get_functor_type_tag */ {
0437             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
0438             out_buffer.members.type.const_qualified = false;
0439             out_buffer.members.type.volatile_qualified = false;
0440           }
0441         }
0442 
0443         // For function objects, we determine whether the function
0444         // object can use the small-object optimization buffer or
0445         // whether we need to allocate it on the heap.
0446         static inline void
0447         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
0448                 functor_manager_operation_type op, function_obj_tag)
0449         {
0450           manager(in_buffer, out_buffer, op,
0451                   std::integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
0452         }
0453 
0454       public:
0455         /* Dispatch to an appropriate manager based on whether we have a
0456            function pointer or a function object pointer. */
0457         static inline void
0458         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
0459                functor_manager_operation_type op)
0460         {
0461           typedef typename get_function_tag<functor_type>::type tag_type;
0462           if (op == get_functor_type_tag) {
0463             out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
0464             out_buffer.members.type.const_qualified = false;
0465             out_buffer.members.type.volatile_qualified = false;
0466           } else {
0467             manager(in_buffer, out_buffer, op, tag_type());
0468           }
0469         }
0470       };
0471 
0472       // A type that is only used for comparisons against zero
0473       struct useless_clear_type {};
0474 
0475       /**
0476        * Stores the "manager" portion of the vtable for a
0477        * boost::function object.
0478        */
0479       struct vtable_base
0480       {
0481         void (*manager)(const function_buffer& in_buffer,
0482                         function_buffer& out_buffer,
0483                         functor_manager_operation_type op);
0484       };
0485     } // end namespace function
0486   } // end namespace detail
0487 
0488 /**
0489  * The function_base class contains the basic elements needed for the
0490  * function1, function2, function3, etc. classes. It is common to all
0491  * functions (and as such can be used to tell if we have one of the
0492  * functionN objects).
0493  */
0494 class function_base
0495 {
0496 public:
0497   function_base() : vtable(0) { }
0498 
0499   /** Determine if the function is empty (i.e., has no target). */
0500   bool empty() const { return !vtable; }
0501 
0502   /** Retrieve the type of the stored function object, or type_id<void>()
0503       if this is empty. */
0504   const boost::core::typeinfo& target_type() const
0505   {
0506     if (!vtable) return BOOST_CORE_TYPEID(void);
0507 
0508     detail::function::function_buffer type;
0509     get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
0510     return *type.members.type.type;
0511   }
0512 
0513   template<typename Functor>
0514     Functor* target()
0515     {
0516       if (!vtable) return 0;
0517 
0518       detail::function::function_buffer type_result;
0519       type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
0520       type_result.members.type.const_qualified = std::is_const<Functor>::value;
0521       type_result.members.type.volatile_qualified = std::is_volatile<Functor>::value;
0522       get_vtable()->manager(functor, type_result,
0523                       detail::function::check_functor_type_tag);
0524       return static_cast<Functor*>(type_result.members.obj_ptr);
0525     }
0526 
0527   template<typename Functor>
0528     const Functor* target() const
0529     {
0530       if (!vtable) return 0;
0531 
0532       detail::function::function_buffer type_result;
0533       type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
0534       type_result.members.type.const_qualified = true;
0535       type_result.members.type.volatile_qualified = std::is_volatile<Functor>::value;
0536       get_vtable()->manager(functor, type_result,
0537                       detail::function::check_functor_type_tag);
0538       // GCC 2.95.3 gets the CV qualifiers wrong here, so we
0539       // can't do the static_cast that we should do.
0540       return static_cast<const Functor*>(type_result.members.obj_ptr);
0541     }
0542 
0543   template<typename F>
0544     typename std::enable_if< !std::is_function<F>::value, bool >::type
0545     contains(const F& f) const
0546     {
0547       if (const F* fp = this->template target<F>())
0548       {
0549         return function_equal(*fp, f);
0550       } else {
0551         return false;
0552       }
0553     }
0554 
0555   template<typename Fn>
0556     typename std::enable_if< std::is_function<Fn>::value, bool >::type
0557     contains(Fn& f) const
0558     {
0559       typedef Fn* F;
0560       if (const F* fp = this->template target<F>())
0561       {
0562         return function_equal(*fp, &f);
0563       } else {
0564         return false;
0565       }
0566     }
0567 
0568 public: // should be protected, but GCC 2.95.3 will fail to allow access
0569   detail::function::vtable_base* get_vtable() const {
0570     return reinterpret_cast<detail::function::vtable_base*>(
0571              reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
0572   }
0573 
0574   bool has_trivial_copy_and_destroy() const {
0575     return reinterpret_cast<std::size_t>(vtable) & 0x01;
0576   }
0577 
0578   detail::function::vtable_base* vtable;
0579   mutable detail::function::function_buffer functor;
0580 };
0581 
0582 #if defined(BOOST_CLANG)
0583 #   pragma clang diagnostic push
0584 #   pragma clang diagnostic ignored "-Wweak-vtables"
0585 #endif
0586 /**
0587  * The bad_function_call exception class is thrown when a boost::function
0588  * object is invoked
0589  */
0590 class BOOST_SYMBOL_VISIBLE bad_function_call : public std::runtime_error
0591 {
0592 public:
0593   bad_function_call() : std::runtime_error("call to empty boost::function") {}
0594 };
0595 #if defined(BOOST_CLANG)
0596 #   pragma clang diagnostic pop
0597 #endif
0598 
0599 inline bool operator==(const function_base& f,
0600                        detail::function::useless_clear_type*)
0601 {
0602   return f.empty();
0603 }
0604 
0605 inline bool operator!=(const function_base& f,
0606                        detail::function::useless_clear_type*)
0607 {
0608   return !f.empty();
0609 }
0610 
0611 inline bool operator==(detail::function::useless_clear_type*,
0612                        const function_base& f)
0613 {
0614   return f.empty();
0615 }
0616 
0617 inline bool operator!=(detail::function::useless_clear_type*,
0618                        const function_base& f)
0619 {
0620   return !f.empty();
0621 }
0622 
0623 // Comparisons between boost::function objects and arbitrary function
0624 // objects.
0625 
0626 template<typename Functor>
0627   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0628   operator==(const function_base& f, Functor g)
0629   {
0630     if (const Functor* fp = f.template target<Functor>())
0631       return function_equal(*fp, g);
0632     else return false;
0633   }
0634 
0635 template<typename Functor>
0636   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0637   operator==(Functor g, const function_base& f)
0638   {
0639     if (const Functor* fp = f.template target<Functor>())
0640       return function_equal(g, *fp);
0641     else return false;
0642   }
0643 
0644 template<typename Functor>
0645   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0646   operator!=(const function_base& f, Functor g)
0647   {
0648     if (const Functor* fp = f.template target<Functor>())
0649       return !function_equal(*fp, g);
0650     else return true;
0651   }
0652 
0653 template<typename Functor>
0654   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0655   operator!=(Functor g, const function_base& f)
0656   {
0657     if (const Functor* fp = f.template target<Functor>())
0658       return !function_equal(g, *fp);
0659     else return true;
0660   }
0661 
0662 template<typename Functor>
0663   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0664   operator==(const function_base& f, reference_wrapper<Functor> g)
0665   {
0666     if (const Functor* fp = f.template target<Functor>())
0667       return fp == g.get_pointer();
0668     else return false;
0669   }
0670 
0671 template<typename Functor>
0672   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0673   operator==(reference_wrapper<Functor> g, const function_base& f)
0674   {
0675     if (const Functor* fp = f.template target<Functor>())
0676       return g.get_pointer() == fp;
0677     else return false;
0678   }
0679 
0680 template<typename Functor>
0681   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0682   operator!=(const function_base& f, reference_wrapper<Functor> g)
0683   {
0684     if (const Functor* fp = f.template target<Functor>())
0685       return fp != g.get_pointer();
0686     else return true;
0687   }
0688 
0689 template<typename Functor>
0690   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
0691   operator!=(reference_wrapper<Functor> g, const function_base& f)
0692   {
0693     if (const Functor* fp = f.template target<Functor>())
0694       return g.get_pointer() != fp;
0695     else return true;
0696   }
0697 
0698 namespace detail {
0699   namespace function {
0700     inline bool has_empty_target(const function_base* f)
0701     {
0702       return f->empty();
0703     }
0704 
0705 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
0706     inline bool has_empty_target(const void*)
0707     {
0708       return false;
0709     }
0710 #else
0711     inline bool has_empty_target(...)
0712     {
0713       return false;
0714     }
0715 #endif
0716   } // end namespace function
0717 } // end namespace detail
0718 } // end namespace boost
0719 
0720 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
0721 
0722 #if defined(BOOST_MSVC)
0723 #   pragma warning( pop )
0724 #endif
0725 
0726 #endif // BOOST_FUNCTION_BASE_HEADER