ossrv_pub/boost_apis/boost/function/function_base.hpp
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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