epoc32/include/stdapis/boost/function/function_base.hpp
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
     1 // Boost.Function library
     2 
     3 //  Copyright Douglas Gregor 2001-2006. Use, modification and
     4 //  distribution is subject to the Boost Software License, Version
     5 //  1.0. (See accompanying file LICENSE_1_0.txt or copy at
     6 //  http://www.boost.org/LICENSE_1_0.txt)
     7 
     8 // For more information, see http://www.boost.org
     9 
    10 #ifndef BOOST_FUNCTION_BASE_HEADER
    11 #define BOOST_FUNCTION_BASE_HEADER
    12 
    13 #include <stdexcept>
    14 #include <string>
    15 #include <memory>
    16 #include <new>
    17 #include <typeinfo>
    18 #include <boost/config.hpp>
    19 #include <boost/assert.hpp>
    20 #include <boost/type_traits/is_integral.hpp>
    21 #include <boost/type_traits/composite_traits.hpp>
    22 #include <boost/ref.hpp>
    23 #include <boost/mpl/if.hpp>
    24 #include <boost/detail/workaround.hpp>
    25 #include <boost/type_traits/alignment_of.hpp>
    26 #ifndef BOOST_NO_SFINAE
    27 #  include "boost/utility/enable_if.hpp"
    28 #else
    29 #  include "boost/mpl/bool.hpp"
    30 #endif
    31 #include <boost/function_equal.hpp>
    32 
    33 // Borrowed from Boost.Python library: determines the cases where we
    34 // need to use std::type_info::name to compare instead of operator==.
    35 # if (defined(__GNUC__) && __GNUC__ >= 3) \
    36  || defined(_AIX) \
    37  || (   defined(__sgi) && defined(__host_mips))
    38 #  include <cstring>
    39 #  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \
    40      (std::strcmp((X).name(),(Y).name()) == 0)
    41 # else
    42 #  define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
    43 #endif
    44 
    45 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
    46 #  define BOOST_FUNCTION_TARGET_FIX(x) x
    47 #else
    48 #  define BOOST_FUNCTION_TARGET_FIX(x)
    49 #endif // not MSVC
    50 
    51 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
    52 // Work around a compiler bug.
    53 // boost::python::objects::function has to be seen by the compiler before the
    54 // boost::function class template.
    55 namespace boost { namespace python { namespace objects {
    56   class function;
    57 }}}
    58 #endif
    59 
    60 #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)                    \
    61  || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG)                         \
    62  || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
    63 #  define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
    64 #endif
    65 
    66 #if !BOOST_WORKAROUND(__BORLANDC__, < 0x600)
    67 #  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)              \
    68       typename ::boost::enable_if_c<(::boost::type_traits::ice_not<          \
    69                             (::boost::is_integral<Functor>::value)>::value), \
    70                            Type>::type
    71 #else
    72 // BCC doesn't recognize this depends on a template argument and complains
    73 // about the use of 'typename'
    74 #  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)     \
    75       ::boost::enable_if_c<(::boost::type_traits::ice_not<          \
    76                    (::boost::is_integral<Functor>::value)>::value), \
    77                        Type>::type
    78 #endif
    79 
    80 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
    81 namespace boost {
    82 
    83 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
    84 // The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
    85 class function_base;
    86 
    87 template<typename Signature,
    88          typename Allocator = std::allocator<function_base> >
    89 class function;
    90 #else
    91 template<typename Signature, typename Allocator = std::allocator<void> >
    92 class function;
    93 #endif
    94 
    95 template<typename Signature, typename Allocator>
    96 inline void swap(function<Signature, Allocator>& f1,
    97                  function<Signature, Allocator>& f2)
    98 {
    99   f1.swap(f2);
   100 }
   101 
   102 } // end namespace boost
   103 #endif // have partial specialization
   104 
   105 namespace boost {
   106   namespace detail {
   107     namespace function {
   108       class X;
   109 
   110       /**
   111        * A buffer used to store small function objects in
   112        * boost::function. It is a union containing function pointers,
   113        * object pointers, and a structure that resembles a bound
   114        * member function pointer.
   115        */
   116       union function_buffer
   117       {
   118         // For pointers to function objects
   119         void* obj_ptr;
   120 
   121         // For pointers to std::type_info objects
   122         // (get_functor_type_tag, check_functor_type_tag).
   123         const void* const_obj_ptr;
   124 
   125         // For function pointers of all kinds
   126         mutable void (*func_ptr)();
   127 
   128         // For bound member pointers
   129         struct bound_memfunc_ptr_t {
   130           void (X::*memfunc_ptr)(int);
   131           void* obj_ptr;
   132         } bound_memfunc_ptr;
   133 
   134         // To relax aliasing constraints
   135         mutable char data;
   136       };
   137 
   138       /**
   139        * The unusable class is a placeholder for unused function arguments
   140        * It is also completely unusable except that it constructable from
   141        * anything. This helps compilers without partial specialization to
   142        * handle Boost.Function objects returning void.
   143        */
   144       struct unusable
   145       {
   146         unusable() {}
   147         template<typename T> unusable(const T&) {}
   148       };
   149 
   150       /* Determine the return type. This supports compilers that do not support
   151        * void returns or partial specialization by silently changing the return
   152        * type to "unusable".
   153        */
   154       template<typename T> struct function_return_type { typedef T type; };
   155 
   156       template<>
   157       struct function_return_type<void>
   158       {
   159         typedef unusable type;
   160       };
   161 
   162       // The operation type to perform on the given functor/function pointer
   163       enum functor_manager_operation_type {
   164         clone_functor_tag,
   165         destroy_functor_tag,
   166         check_functor_type_tag,
   167         get_functor_type_tag
   168       };
   169 
   170       // Tags used to decide between different types of functions
   171       struct function_ptr_tag {};
   172       struct function_obj_tag {};
   173       struct member_ptr_tag {};
   174       struct function_obj_ref_tag {};
   175 
   176       template<typename F>
   177       class get_function_tag
   178       {
   179         typedef typename mpl::if_c<(is_pointer<F>::value),
   180                                    function_ptr_tag,
   181                                    function_obj_tag>::type ptr_or_obj_tag;
   182 
   183         typedef typename mpl::if_c<(is_member_pointer<F>::value),
   184                                    member_ptr_tag,
   185                                    ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
   186 
   187         typedef typename mpl::if_c<(is_reference_wrapper<F>::value),
   188                                    function_obj_ref_tag,
   189                                    ptr_or_obj_or_mem_tag>::type or_ref_tag;
   190 
   191       public:
   192         typedef or_ref_tag type;
   193       };
   194 
   195       // The trivial manager does nothing but return the same pointer (if we
   196       // are cloning) or return the null pointer (if we are deleting).
   197       template<typename F>
   198       struct reference_manager
   199       {
   200         static inline void
   201         get(const function_buffer& in_buffer, function_buffer& out_buffer, 
   202             functor_manager_operation_type op)
   203         {
   204           switch (op) {
   205           case clone_functor_tag: 
   206             out_buffer.obj_ptr = in_buffer.obj_ptr;
   207             return;
   208 
   209           case destroy_functor_tag:
   210             out_buffer.obj_ptr = 0;
   211             return;
   212 
   213           case check_functor_type_tag:
   214             {
   215               // DPG TBD: Since we're only storing a pointer, it's
   216               // possible that the user could ask for a base class or
   217               // derived class. Is that okay?
   218               const std::type_info& check_type = 
   219                 *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
   220               if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
   221                 out_buffer.obj_ptr = in_buffer.obj_ptr;
   222               else
   223                 out_buffer.obj_ptr = 0;
   224             }
   225             return;
   226 
   227           case get_functor_type_tag:
   228             out_buffer.const_obj_ptr = &typeid(F);
   229             return;
   230           }
   231         }
   232       };
   233 
   234       /**
   235        * Determine if boost::function can use the small-object
   236        * optimization with the function object type F.
   237        */
   238       template<typename F>
   239       struct function_allows_small_object_optimization
   240       {
   241         BOOST_STATIC_CONSTANT
   242           (bool, 
   243            value = ((sizeof(F) <= sizeof(function_buffer) &&
   244                      (alignment_of<function_buffer>::value 
   245                       % alignment_of<F>::value == 0))));
   246       };
   247 
   248       /**
   249        * The functor_manager class contains a static function "manage" which
   250        * can clone or destroy the given function/function object pointer.
   251        */
   252       template<typename Functor, typename Allocator>
   253       struct functor_manager
   254       {
   255       private:
   256         typedef Functor functor_type;
   257 
   258         // For function pointers, the manager is trivial
   259         static inline void
   260         manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
   261                 functor_manager_operation_type op, function_ptr_tag)
   262         {
   263           if (op == clone_functor_tag)
   264             out_buffer.func_ptr = in_buffer.func_ptr;
   265           else if (op == destroy_functor_tag)
   266             out_buffer.func_ptr = 0;
   267           else /* op == check_functor_type_tag */ {
   268             const std::type_info& check_type = 
   269               *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
   270             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
   271               out_buffer.obj_ptr = &in_buffer.func_ptr;
   272             else
   273               out_buffer.obj_ptr = 0;
   274           }
   275         }
   276 
   277         // Function objects that fit in the small-object buffer.
   278         static inline void
   279         manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
   280                 functor_manager_operation_type op, mpl::true_)
   281         {
   282           if (op == clone_functor_tag) {
   283             const functor_type* in_functor = 
   284               reinterpret_cast<const functor_type*>(&in_buffer.data);
   285             new ((void*)&out_buffer.data) functor_type(*in_functor);
   286           } else if (op == destroy_functor_tag) {
   287             // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
   288             reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
   289           } else /* op == check_functor_type_tag */ {
   290             const std::type_info& check_type = 
   291               *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
   292             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
   293               out_buffer.obj_ptr = &in_buffer.data;
   294             else
   295               out_buffer.obj_ptr = 0;
   296           }
   297         }
   298         
   299         // Function objects that require heap allocation
   300         static inline void
   301         manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
   302                 functor_manager_operation_type op, mpl::false_)
   303         {
   304 #ifndef BOOST_NO_STD_ALLOCATOR
   305           typedef typename Allocator::template rebind<functor_type>::other
   306             allocator_type;
   307           typedef typename allocator_type::pointer pointer_type;
   308 #else
   309           typedef functor_type* pointer_type;
   310 #endif // BOOST_NO_STD_ALLOCATOR
   311 
   312 #  ifndef BOOST_NO_STD_ALLOCATOR
   313           allocator_type allocator;
   314 #  endif // BOOST_NO_STD_ALLOCATOR
   315 
   316           if (op == clone_functor_tag) {
   317             // GCC 2.95.3 gets the CV qualifiers wrong here, so we
   318             // can't do the static_cast that we should do.
   319             const functor_type* f =
   320               (const functor_type*)(in_buffer.obj_ptr);
   321 
   322             // Clone the functor
   323 #  ifndef BOOST_NO_STD_ALLOCATOR
   324             pointer_type copy = allocator.allocate(1);
   325             allocator.construct(copy, *f);
   326 
   327             // Get back to the original pointer type
   328             functor_type* new_f = static_cast<functor_type*>(copy);
   329 #  else
   330             functor_type* new_f = new functor_type(*f);
   331 #  endif // BOOST_NO_STD_ALLOCATOR
   332             out_buffer.obj_ptr = new_f;
   333           } else if (op == destroy_functor_tag) {
   334             /* Cast from the void pointer to the functor pointer type */
   335             functor_type* f =
   336               static_cast<functor_type*>(out_buffer.obj_ptr);
   337 
   338 #  ifndef BOOST_NO_STD_ALLOCATOR
   339             /* Cast from the functor pointer type to the allocator's pointer
   340                type */
   341             pointer_type victim = static_cast<pointer_type>(f);
   342 
   343             // Destroy and deallocate the functor
   344             allocator.destroy(victim);
   345             allocator.deallocate(victim, 1);
   346 #  else
   347             delete f;
   348 #  endif // BOOST_NO_STD_ALLOCATOR
   349             out_buffer.obj_ptr = 0;
   350           } else /* op == check_functor_type_tag */ {
   351             const std::type_info& check_type = 
   352               *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
   353             if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
   354               out_buffer.obj_ptr = in_buffer.obj_ptr;
   355             else
   356               out_buffer.obj_ptr = 0;
   357           }
   358         }
   359 
   360         // For function objects, we determine whether the function
   361         // object can use the small-object optimization buffer or
   362         // whether we need to allocate it on the heap.
   363         static inline void
   364         manager(const function_buffer& in_buffer, function_buffer& out_buffer, 
   365                 functor_manager_operation_type op, function_obj_tag)
   366         {
   367           manager(in_buffer, out_buffer, op,
   368                   mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
   369         }
   370 
   371       public:
   372         /* Dispatch to an appropriate manager based on whether we have a
   373            function pointer or a function object pointer. */
   374         static inline void
   375         manage(const function_buffer& in_buffer, function_buffer& out_buffer, 
   376                functor_manager_operation_type op)
   377         {
   378           typedef typename get_function_tag<functor_type>::type tag_type;
   379           switch (op) {
   380           case get_functor_type_tag:
   381             out_buffer.const_obj_ptr = &typeid(functor_type);
   382             return;
   383 
   384           default:
   385             manager(in_buffer, out_buffer, op, tag_type());
   386             return;
   387           }
   388         }
   389       };
   390 
   391       // A type that is only used for comparisons against zero
   392       struct useless_clear_type {};
   393 
   394 #ifdef BOOST_NO_SFINAE
   395       // These routines perform comparisons between a Boost.Function
   396       // object and an arbitrary function object (when the last
   397       // parameter is mpl::bool_<false>) or against zero (when the
   398       // last parameter is mpl::bool_<true>). They are only necessary
   399       // for compilers that don't support SFINAE.
   400       template<typename Function, typename Functor>
   401         bool
   402         compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>)
   403         { return f.empty(); }
   404 
   405       template<typename Function, typename Functor>
   406         bool
   407         compare_not_equal(const Function& f, const Functor&, int,
   408                           mpl::bool_<true>)
   409         { return !f.empty(); }
   410 
   411       template<typename Function, typename Functor>
   412         bool
   413         compare_equal(const Function& f, const Functor& g, long,
   414                       mpl::bool_<false>)
   415         {
   416           if (const Functor* fp = f.template target<Functor>())
   417             return function_equal(*fp, g);
   418           else return false;
   419         }
   420 
   421       template<typename Function, typename Functor>
   422         bool
   423         compare_equal(const Function& f, const reference_wrapper<Functor>& g,
   424                       int, mpl::bool_<false>)
   425         {
   426           if (const Functor* fp = f.template target<Functor>())
   427             return fp == g.get_pointer();
   428           else return false;
   429         }
   430 
   431       template<typename Function, typename Functor>
   432         bool
   433         compare_not_equal(const Function& f, const Functor& g, long,
   434                           mpl::bool_<false>)
   435         {
   436           if (const Functor* fp = f.template target<Functor>())
   437             return !function_equal(*fp, g);
   438           else return true;
   439         }
   440 
   441       template<typename Function, typename Functor>
   442         bool
   443         compare_not_equal(const Function& f,
   444                           const reference_wrapper<Functor>& g, int,
   445                           mpl::bool_<false>)
   446         {
   447           if (const Functor* fp = f.template target<Functor>())
   448             return fp != g.get_pointer();
   449           else return true;
   450         }
   451 #endif // BOOST_NO_SFINAE
   452 
   453       /**
   454        * Stores the "manager" portion of the vtable for a
   455        * boost::function object.
   456        */
   457       struct vtable_base
   458       {
   459         vtable_base() : manager(0) { }
   460         void (*manager)(const function_buffer& in_buffer, 
   461                         function_buffer& out_buffer, 
   462                         functor_manager_operation_type op);
   463       };
   464     } // end namespace function
   465   } // end namespace detail
   466 
   467 /**
   468  * The function_base class contains the basic elements needed for the
   469  * function1, function2, function3, etc. classes. It is common to all
   470  * functions (and as such can be used to tell if we have one of the
   471  * functionN objects).
   472  */
   473 class function_base
   474 {
   475 public:
   476   function_base() : vtable(0) { }
   477 
   478   /** Determine if the function is empty (i.e., has no target). */
   479   bool empty() const { return !vtable; }
   480 
   481   /** Retrieve the type of the stored function object, or typeid(void)
   482       if this is empty. */
   483   const std::type_info& target_type() const
   484   {
   485     if (!vtable) return typeid(void);
   486 
   487     detail::function::function_buffer type;
   488     vtable->manager(functor, type, detail::function::get_functor_type_tag);
   489     return *static_cast<const std::type_info*>(type.const_obj_ptr);
   490   }
   491 
   492   template<typename Functor>
   493     Functor* target()
   494     {
   495       if (!vtable) return 0;
   496 
   497       detail::function::function_buffer type_result;
   498       type_result.const_obj_ptr = &typeid(Functor);
   499       vtable->manager(functor, type_result, 
   500                       detail::function::check_functor_type_tag);
   501       return static_cast<Functor*>(type_result.obj_ptr);
   502     }
   503 
   504   template<typename Functor>
   505 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
   506     const Functor* target( Functor * = 0 ) const
   507 #else
   508     const Functor* target() const
   509 #endif
   510     {
   511       if (!vtable) return 0;
   512 
   513       detail::function::function_buffer type_result;
   514       type_result.const_obj_ptr = &typeid(Functor);
   515       vtable->manager(functor, type_result, 
   516                       detail::function::check_functor_type_tag);
   517       // GCC 2.95.3 gets the CV qualifiers wrong here, so we
   518       // can't do the static_cast that we should do.
   519       return (const Functor*)(type_result.obj_ptr);
   520     }
   521 
   522   template<typename F>
   523     bool contains(const F& f) const
   524     {
   525 #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
   526       if (const F* fp = this->target( (F*)0 ))
   527 #else
   528       if (const F* fp = this->template target<F>())
   529 #endif
   530       {
   531         return function_equal(*fp, f);
   532       } else {
   533         return false;
   534       }
   535     }
   536 
   537 #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3
   538   // GCC 3.3 and newer cannot copy with the global operator==, due to
   539   // problems with instantiation of function return types before it
   540   // has been verified that the argument types match up.
   541   template<typename Functor>
   542     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
   543     operator==(Functor g) const
   544     {
   545       if (const Functor* fp = target<Functor>())
   546         return function_equal(*fp, g);
   547       else return false;
   548     }
   549 
   550   template<typename Functor>
   551     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
   552     operator!=(Functor g) const
   553     {
   554       if (const Functor* fp = target<Functor>())
   555         return !function_equal(*fp, g);
   556       else return true;
   557     }
   558 #endif
   559 
   560 public: // should be protected, but GCC 2.95.3 will fail to allow access
   561   detail::function::vtable_base* vtable;
   562   mutable detail::function::function_buffer functor;
   563 };
   564 
   565 /**
   566  * The bad_function_call exception class is thrown when a boost::function
   567  * object is invoked
   568  */
   569 class bad_function_call : public std::runtime_error
   570 {
   571 public:
   572   bad_function_call() : std::runtime_error("call to empty boost::function") {}
   573 };
   574 
   575 #ifndef BOOST_NO_SFINAE
   576 inline bool operator==(const function_base& f,
   577                        detail::function::useless_clear_type*)
   578 {
   579   return f.empty();
   580 }
   581 
   582 inline bool operator!=(const function_base& f,
   583                        detail::function::useless_clear_type*)
   584 {
   585   return !f.empty();
   586 }
   587 
   588 inline bool operator==(detail::function::useless_clear_type*,
   589                        const function_base& f)
   590 {
   591   return f.empty();
   592 }
   593 
   594 inline bool operator!=(detail::function::useless_clear_type*,
   595                        const function_base& f)
   596 {
   597   return !f.empty();
   598 }
   599 #endif
   600 
   601 #ifdef BOOST_NO_SFINAE
   602 // Comparisons between boost::function objects and arbitrary function objects
   603 template<typename Functor>
   604   inline bool operator==(const function_base& f, Functor g)
   605   {
   606     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
   607     return detail::function::compare_equal(f, g, 0, integral());
   608   }
   609 
   610 template<typename Functor>
   611   inline bool operator==(Functor g, const function_base& f)
   612   {
   613     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
   614     return detail::function::compare_equal(f, g, 0, integral());
   615   }
   616 
   617 template<typename Functor>
   618   inline bool operator!=(const function_base& f, Functor g)
   619   {
   620     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
   621     return detail::function::compare_not_equal(f, g, 0, integral());
   622   }
   623 
   624 template<typename Functor>
   625   inline bool operator!=(Functor g, const function_base& f)
   626   {
   627     typedef mpl::bool_<(is_integral<Functor>::value)> integral;
   628     return detail::function::compare_not_equal(f, g, 0, integral());
   629   }
   630 #else
   631 
   632 #  if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3)
   633 // Comparisons between boost::function objects and arbitrary function
   634 // objects. GCC 3.3 and before has an obnoxious bug that prevents this
   635 // from working.
   636 template<typename Functor>
   637   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
   638   operator==(const function_base& f, Functor g)
   639   {
   640     if (const Functor* fp = f.template target<Functor>())
   641       return function_equal(*fp, g);
   642     else return false;
   643   }
   644 
   645 template<typename Functor>
   646   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
   647   operator==(Functor g, const function_base& f)
   648   {
   649     if (const Functor* fp = f.template target<Functor>())
   650       return function_equal(g, *fp);
   651     else return false;
   652   }
   653 
   654 template<typename Functor>
   655   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
   656   operator!=(const function_base& f, Functor g)
   657   {
   658     if (const Functor* fp = f.template target<Functor>())
   659       return !function_equal(*fp, g);
   660     else return true;
   661   }
   662 
   663 template<typename Functor>
   664   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
   665   operator!=(Functor g, const function_base& f)
   666   {
   667     if (const Functor* fp = f.template target<Functor>())
   668       return !function_equal(g, *fp);
   669     else return true;
   670   }
   671 #  endif
   672 
   673 template<typename Functor>
   674   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
   675   operator==(const function_base& f, reference_wrapper<Functor> g)
   676   {
   677     if (const Functor* fp = f.template target<Functor>())
   678       return fp == g.get_pointer();
   679     else return false;
   680   }
   681 
   682 template<typename Functor>
   683   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
   684   operator==(reference_wrapper<Functor> g, const function_base& f)
   685   {
   686     if (const Functor* fp = f.template target<Functor>())
   687       return g.get_pointer() == fp;
   688     else return false;
   689   }
   690 
   691 template<typename Functor>
   692   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
   693   operator!=(const function_base& f, reference_wrapper<Functor> g)
   694   {
   695     if (const Functor* fp = f.template target<Functor>())
   696       return fp != g.get_pointer();
   697     else return true;
   698   }
   699 
   700 template<typename Functor>
   701   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
   702   operator!=(reference_wrapper<Functor> g, const function_base& f)
   703   {
   704     if (const Functor* fp = f.template target<Functor>())
   705       return g.get_pointer() != fp;
   706     else return true;
   707   }
   708 
   709 #endif // Compiler supporting SFINAE
   710 
   711 namespace detail {
   712   namespace function {
   713     inline bool has_empty_target(const function_base* f)
   714     {
   715       return f->empty();
   716     }
   717 
   718 #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
   719     inline bool has_empty_target(const void*)
   720     {
   721       return false;
   722     }
   723 #else
   724     inline bool has_empty_target(...)
   725     {
   726       return false;
   727     }
   728 #endif
   729   } // end namespace function
   730 } // end namespace detail
   731 } // end namespace boost
   732 
   733 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
   734 #undef BOOST_FUNCTION_COMPARE_TYPE_ID
   735 
   736 #endif // BOOST_FUNCTION_BASE_HEADER