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