LCOV - code coverage report
Current view: top level - opt/homebrew/include/boost/function - function_base.hpp (source / functions) Hit Total Coverage
Test: test_dash_coverage.info Lines: 55 85 64.7 %
Date: 2026-06-25 07:23:51 Functions: 31 97 32.0 %

          Line data    Source code
       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 <boost/function/function_fwd.hpp>
      15             : #include <boost/function_equal.hpp>
      16             : #include <boost/core/typeinfo.hpp>
      17             : #include <boost/core/ref.hpp>
      18             : #include <boost/assert.hpp>
      19             : #include <boost/config.hpp>
      20             : #include <boost/config/workaround.hpp>
      21             : #include <stdexcept>
      22             : #include <string>
      23             : #include <memory>
      24             : #include <new>
      25             : #include <type_traits>
      26             : 
      27             : #if defined(BOOST_MSVC)
      28             : #   pragma warning( push )
      29             : #   pragma warning( disable : 4793 ) // complaint about native code generation
      30             : #   pragma warning( disable : 4127 ) // "conditional expression is constant"
      31             : #endif
      32             : 
      33             : // retained because used in a test
      34             : #define BOOST_FUNCTION_TARGET_FIX(x)
      35             : 
      36             : #define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
      37             :   typename std::enable_if< !std::is_integral<Functor>::value, Type>::type
      38             : 
      39             : namespace boost {
      40             :   namespace detail {
      41             :     namespace function {
      42             :       class X;
      43             : 
      44             :       /**
      45             :        * A buffer used to store small function objects in
      46             :        * boost::function. It is a union containing function pointers,
      47             :        * object pointers, and a structure that resembles a bound
      48             :        * member function pointer.
      49             :        */
      50             :       union function_buffer_members
      51             :       {
      52             :         // For pointers to function objects
      53             :         typedef void* obj_ptr_t;
      54             :         mutable obj_ptr_t obj_ptr;
      55             : 
      56             :         // For pointers to std::type_info objects
      57             :         struct type_t {
      58             :           // (get_functor_type_tag, check_functor_type_tag).
      59             :           const boost::core::typeinfo* type;
      60             : 
      61             :           // Whether the type is const-qualified.
      62             :           bool const_qualified;
      63             :           // Whether the type is volatile-qualified.
      64             :           bool volatile_qualified;
      65             :         } type;
      66             : 
      67             :         // For function pointers of all kinds
      68             :         typedef void (*func_ptr_t)();
      69             :         mutable func_ptr_t func_ptr;
      70             : 
      71             : #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
      72             : # pragma warning(push)
      73             : # pragma warning(disable: 5243)
      74             : #endif
      75             : 
      76             :         // For bound member pointers
      77             :         struct bound_memfunc_ptr_t {
      78             :           void (X::*memfunc_ptr)(int);
      79             :           void* obj_ptr;
      80             :         } bound_memfunc_ptr;
      81             : 
      82             : #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
      83             : # pragma warning(pop)
      84             : #endif
      85             : 
      86             :         // For references to function objects. We explicitly keep
      87             :         // track of the cv-qualifiers on the object referenced.
      88             :         struct obj_ref_t {
      89             :           mutable void* obj_ptr;
      90             :           bool is_const_qualified;
      91             :           bool is_volatile_qualified;
      92             :         } obj_ref;
      93             :       };
      94             : 
      95             :       union BOOST_SYMBOL_VISIBLE function_buffer
      96             :       {
      97             :         // Type-specific union members
      98             :         mutable function_buffer_members members;
      99             : 
     100             :         // To relax aliasing constraints
     101             :         mutable char data[sizeof(function_buffer_members)];
     102             :       };
     103             : 
     104             :       // The operation type to perform on the given functor/function pointer
     105             :       enum functor_manager_operation_type {
     106             :         clone_functor_tag,
     107             :         move_functor_tag,
     108             :         destroy_functor_tag,
     109             :         check_functor_type_tag,
     110             :         get_functor_type_tag
     111             :       };
     112             : 
     113             :       // Tags used to decide between different types of functions
     114             :       struct function_ptr_tag {};
     115             :       struct function_obj_tag {};
     116             :       struct member_ptr_tag {};
     117             :       struct function_obj_ref_tag {};
     118             : 
     119             :       template<typename F>
     120             :       class get_function_tag
     121             :       {
     122             :         typedef typename std::conditional<std::is_pointer<F>::value,
     123             :                                    function_ptr_tag,
     124             :                                    function_obj_tag>::type ptr_or_obj_tag;
     125             : 
     126             :         typedef typename std::conditional<std::is_member_pointer<F>::value,
     127             :                                    member_ptr_tag,
     128             :                                    ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
     129             : 
     130             :         typedef typename std::conditional<is_reference_wrapper<F>::value,
     131             :                                    function_obj_ref_tag,
     132             :                                    ptr_or_obj_or_mem_tag>::type or_ref_tag;
     133             : 
     134             :       public:
     135             :         typedef or_ref_tag type;
     136             :       };
     137             : 
     138             :       // The trivial manager does nothing but return the same pointer (if we
     139             :       // are cloning) or return the null pointer (if we are deleting).
     140             :       template<typename F>
     141             :       struct reference_manager
     142             :       {
     143             :         static inline void
     144             :         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
     145             :                functor_manager_operation_type op)
     146             :         {
     147             :           switch (op) {
     148             :           case clone_functor_tag:
     149             :             out_buffer.members.obj_ref = in_buffer.members.obj_ref;
     150             :             return;
     151             : 
     152             :           case move_functor_tag:
     153             :             out_buffer.members.obj_ref = in_buffer.members.obj_ref;
     154             :             in_buffer.members.obj_ref.obj_ptr = 0;
     155             :             return;
     156             : 
     157             :           case destroy_functor_tag:
     158             :             out_buffer.members.obj_ref.obj_ptr = 0;
     159             :             return;
     160             : 
     161             :           case check_functor_type_tag:
     162             :             {
     163             :               // Check whether we have the same type. We can add
     164             :               // cv-qualifiers, but we can't take them away.
     165             :               if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(F)
     166             :                   && (!in_buffer.members.obj_ref.is_const_qualified
     167             :                       || out_buffer.members.type.const_qualified)
     168             :                   && (!in_buffer.members.obj_ref.is_volatile_qualified
     169             :                       || out_buffer.members.type.volatile_qualified))
     170             :                 out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
     171             :               else
     172             :                 out_buffer.members.obj_ptr = 0;
     173             :             }
     174             :             return;
     175             : 
     176             :           case get_functor_type_tag:
     177             :             out_buffer.members.type.type = &BOOST_CORE_TYPEID(F);
     178             :             out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
     179             :             out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
     180             :             return;
     181             :           }
     182             :         }
     183             :       };
     184             : 
     185             :       /**
     186             :        * Determine if boost::function can use the small-object
     187             :        * optimization with the function object type F.
     188             :        */
     189             :       template<typename F>
     190             :       struct function_allows_small_object_optimization
     191             :       {
     192             :         BOOST_STATIC_CONSTANT
     193             :           (bool,
     194             :            value = ((sizeof(F) <= sizeof(function_buffer) &&
     195             :                      (std::alignment_of<function_buffer>::value
     196             :                       % std::alignment_of<F>::value == 0))));
     197             :       };
     198             : 
     199             :       template <typename F,typename A>
     200             :       struct functor_wrapper: public F, public A
     201             :       {
     202             :         functor_wrapper( F f, A a ):
     203             :           F(f),
     204             :           A(a)
     205             :         {
     206             :         }
     207             : 
     208             :         functor_wrapper(const functor_wrapper& f) :
     209             :           F(static_cast<const F&>(f)),
     210             :           A(static_cast<const A&>(f))
     211             :         {
     212             :         }
     213             :       };
     214             : 
     215             :       /**
     216             :        * The functor_manager class contains a static function "manage" which
     217             :        * can clone or destroy the given function/function object pointer.
     218             :        */
     219             :       template<typename Functor>
     220             :       struct functor_manager_common
     221             :       {
     222             :         typedef Functor functor_type;
     223             : 
     224             :         // Function pointers
     225             :         static inline void
     226      101762 :         manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
     227             :                 functor_manager_operation_type op)
     228             :         {
     229      101762 :           if (op == clone_functor_tag)
     230           0 :             out_buffer.members.func_ptr = in_buffer.members.func_ptr;
     231      101762 :           else if (op == move_functor_tag) {
     232           0 :             out_buffer.members.func_ptr = in_buffer.members.func_ptr;
     233           0 :             in_buffer.members.func_ptr = 0;
     234      101762 :           } else if (op == destroy_functor_tag)
     235      101762 :             out_buffer.members.func_ptr = 0;
     236           0 :           else if (op == check_functor_type_tag) {
     237           0 :             if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
     238           0 :               out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
     239             :             else
     240           0 :               out_buffer.members.obj_ptr = 0;
     241           0 :           } else /* op == get_functor_type_tag */ {
     242           0 :             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
     243           0 :             out_buffer.members.type.const_qualified = false;
     244           0 :             out_buffer.members.type.volatile_qualified = false;
     245             :           }
     246      101762 :         }
     247             : 
     248             :         // Function objects that fit in the small-object buffer.
     249             :         static inline void
     250         286 :         manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
     251             :                 functor_manager_operation_type op)
     252             :         {
     253         286 :           if (op == clone_functor_tag) {
     254          28 :             const functor_type* in_functor =
     255          28 :               reinterpret_cast<const functor_type*>(in_buffer.data);
     256          28 :             new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
     257             : 
     258         286 :           } else if (op == move_functor_tag) {
     259          56 :               functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
     260          56 :               new (reinterpret_cast<void*>(out_buffer.data)) functor_type(std::move(*f));
     261          56 :               f->~Functor();
     262         258 :           } else if (op == destroy_functor_tag) {
     263             :             // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
     264         202 :              functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data);
     265             :              (void)f; // suppress warning about the value of f not being used (MSVC)
     266         202 :              f->~Functor();
     267         202 :           } else if (op == check_functor_type_tag) {
     268           0 :              if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
     269           0 :               out_buffer.members.obj_ptr = in_buffer.data;
     270             :             else
     271           0 :               out_buffer.members.obj_ptr = 0;
     272           0 :           } else /* op == get_functor_type_tag */ {
     273           0 :             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
     274           0 :             out_buffer.members.type.const_qualified = false;
     275           0 :             out_buffer.members.type.volatile_qualified = false;
     276             :           }
     277         286 :         }
     278             :       };
     279             : 
     280             :       template<typename Functor>
     281             :       struct functor_manager
     282             :       {
     283             :       private:
     284             :         typedef Functor functor_type;
     285             : 
     286             :         // Function pointers
     287             :         static inline void
     288      101762 :         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
     289             :                 functor_manager_operation_type op, function_ptr_tag)
     290             :         {
     291      101762 :           functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
     292      101762 :         }
     293             : 
     294             :         // Function objects that fit in the small-object buffer.
     295             :         static inline void
     296         286 :         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
     297             :                 functor_manager_operation_type op, std::true_type)
     298             :         {
     299         286 :           functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
     300         286 :         }
     301             : 
     302             :         // Function objects that require heap allocation
     303             :         static inline void
     304        3510 :         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
     305             :                 functor_manager_operation_type op, std::false_type)
     306             :         {
     307        3510 :           if (op == clone_functor_tag) {
     308             :             // Clone the functor
     309             :             // GCC 2.95.3 gets the CV qualifiers wrong here, so we
     310             :             // can't do the static_cast that we should do.
     311             :             // jewillco: Changing this to static_cast because GCC 2.95.3 is
     312             :             // obsolete.
     313         684 :             const functor_type* f =
     314         684 :               static_cast<const functor_type*>(in_buffer.members.obj_ptr);
     315         684 :             functor_type* new_f = new functor_type(*f);
     316         684 :             out_buffer.members.obj_ptr = new_f;
     317        3510 :           } else if (op == move_functor_tag) {
     318        1368 :             out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
     319        1368 :             in_buffer.members.obj_ptr = 0;
     320        2826 :           } else if (op == destroy_functor_tag) {
     321             :             /* Cast from the void pointer to the functor pointer type */
     322        1458 :             functor_type* f =
     323        1458 :               static_cast<functor_type*>(out_buffer.members.obj_ptr);
     324        1458 :             delete f;
     325        1458 :             out_buffer.members.obj_ptr = 0;
     326        1458 :           } else if (op == check_functor_type_tag) {
     327           0 :             if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
     328           0 :               out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
     329             :             else
     330           0 :               out_buffer.members.obj_ptr = 0;
     331           0 :           } else /* op == get_functor_type_tag */ {
     332           0 :             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
     333           0 :             out_buffer.members.type.const_qualified = false;
     334           0 :             out_buffer.members.type.volatile_qualified = false;
     335             :           }
     336        3510 :         }
     337             : 
     338             :         // For function objects, we determine whether the function
     339             :         // object can use the small-object optimization buffer or
     340             :         // whether we need to allocate it on the heap.
     341             :         static inline void
     342        3796 :         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
     343             :                 functor_manager_operation_type op, function_obj_tag)
     344             :         {
     345        3796 :           manager(in_buffer, out_buffer, op,
     346             :                   std::integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
     347        3796 :         }
     348             : 
     349             :         // For member pointers, we use the small-object optimization buffer.
     350             :         static inline void
     351             :         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
     352             :                 functor_manager_operation_type op, member_ptr_tag)
     353             :         {
     354             :           manager(in_buffer, out_buffer, op, std::true_type());
     355             :         }
     356             : 
     357             :       public:
     358             :         /* Dispatch to an appropriate manager based on whether we have a
     359             :            function pointer or a function object pointer. */
     360             :         static inline void
     361      105558 :         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
     362             :                functor_manager_operation_type op)
     363             :         {
     364             :           typedef typename get_function_tag<functor_type>::type tag_type;
     365      105558 :           if (op == get_functor_type_tag) {
     366           0 :             out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
     367           0 :             out_buffer.members.type.const_qualified = false;
     368           0 :             out_buffer.members.type.volatile_qualified = false;
     369           0 :           } else {
     370      105558 :             manager(in_buffer, out_buffer, op, tag_type());
     371             :           }
     372      105558 :         }
     373             :       };
     374             : 
     375             :       template<typename Functor, typename Allocator>
     376             :       struct functor_manager_a
     377             :       {
     378             :       private:
     379             :         typedef Functor functor_type;
     380             : 
     381             :         // Function pointers
     382             :         static inline void
     383             :         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
     384             :                 functor_manager_operation_type op, function_ptr_tag)
     385             :         {
     386             :           functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
     387             :         }
     388             : 
     389             :         // Function objects that fit in the small-object buffer.
     390             :         static inline void
     391             :         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
     392             :                 functor_manager_operation_type op, std::true_type)
     393             :         {
     394             :           functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
     395             :         }
     396             : 
     397             :         // Function objects that require heap allocation
     398             :         static inline void
     399             :         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
     400             :                 functor_manager_operation_type op, std::false_type)
     401             :         {
     402             :           typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
     403             : 
     404             :           using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
     405             :           using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
     406             : 
     407             :           if (op == clone_functor_tag) {
     408             :             // Clone the functor
     409             :             // GCC 2.95.3 gets the CV qualifiers wrong here, so we
     410             :             // can't do the static_cast that we should do.
     411             :             const functor_wrapper_type* f =
     412             :               static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
     413             :             wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
     414             :             wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
     415             :             std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, *f);
     416             : 
     417             :             // Get back to the original pointer type
     418             :             functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
     419             :             out_buffer.members.obj_ptr = new_f;
     420             :           } else if (op == move_functor_tag) {
     421             :             out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
     422             :             in_buffer.members.obj_ptr = 0;
     423             :           } else if (op == destroy_functor_tag) {
     424             :             /* Cast from the void pointer to the functor_wrapper_type */
     425             :             functor_wrapper_type* victim =
     426             :               static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
     427             :             wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
     428             :             std::allocator_traits<wrapper_allocator_type>::destroy(wrapper_allocator, victim);
     429             :             wrapper_allocator.deallocate(victim,1);
     430             :             out_buffer.members.obj_ptr = 0;
     431             :           } else if (op == check_functor_type_tag) {
     432             :             if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
     433             :               out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
     434             :             else
     435             :               out_buffer.members.obj_ptr = 0;
     436             :           } else /* op == get_functor_type_tag */ {
     437             :             out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
     438             :             out_buffer.members.type.const_qualified = false;
     439             :             out_buffer.members.type.volatile_qualified = false;
     440             :           }
     441             :         }
     442             : 
     443             :         // For function objects, we determine whether the function
     444             :         // object can use the small-object optimization buffer or
     445             :         // whether we need to allocate it on the heap.
     446             :         static inline void
     447             :         manager(const function_buffer& in_buffer, function_buffer& out_buffer,
     448             :                 functor_manager_operation_type op, function_obj_tag)
     449             :         {
     450             :           manager(in_buffer, out_buffer, op,
     451             :                   std::integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
     452             :         }
     453             : 
     454             :       public:
     455             :         /* Dispatch to an appropriate manager based on whether we have a
     456             :            function pointer or a function object pointer. */
     457             :         static inline void
     458             :         manage(const function_buffer& in_buffer, function_buffer& out_buffer,
     459             :                functor_manager_operation_type op)
     460             :         {
     461             :           typedef typename get_function_tag<functor_type>::type tag_type;
     462             :           if (op == get_functor_type_tag) {
     463             :             out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
     464             :             out_buffer.members.type.const_qualified = false;
     465             :             out_buffer.members.type.volatile_qualified = false;
     466             :           } else {
     467             :             manager(in_buffer, out_buffer, op, tag_type());
     468             :           }
     469             :         }
     470             :       };
     471             : 
     472             :       // A type that is only used for comparisons against zero
     473             :       struct useless_clear_type {};
     474             : 
     475             :       /**
     476             :        * Stores the "manager" portion of the vtable for a
     477             :        * boost::function object.
     478             :        */
     479             :       struct vtable_base
     480             :       {
     481             :         void (*manager)(const function_buffer& in_buffer,
     482             :                         function_buffer& out_buffer,
     483             :                         functor_manager_operation_type op);
     484             :       };
     485             :     } // end namespace function
     486             :   } // end namespace detail
     487             : 
     488             : /**
     489             :  * The function_base class contains the basic elements needed for the
     490             :  * function1, function2, function3, etc. classes. It is common to all
     491             :  * functions (and as such can be used to tell if we have one of the
     492             :  * functionN objects).
     493             :  */
     494             : class function_base
     495             : {
     496             : public:
     497      220972 :   function_base() : vtable(0) { }
     498             : 
     499             :   /** Determine if the function is empty (i.e., has no target). */
     500      119592 :   bool empty() const { return !vtable; }
     501             : 
     502             :   /** Retrieve the type of the stored function object, or type_id<void>()
     503             :       if this is empty. */
     504             :   const boost::core::typeinfo& target_type() const
     505             :   {
     506             :     if (!vtable) return BOOST_CORE_TYPEID(void);
     507             : 
     508             :     detail::function::function_buffer type;
     509             :     get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
     510             :     return *type.members.type.type;
     511             :   }
     512             : 
     513             :   template<typename Functor>
     514             :     Functor* target()
     515             :     {
     516             :       if (!vtable) return 0;
     517             : 
     518             :       detail::function::function_buffer type_result;
     519             :       type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
     520             :       type_result.members.type.const_qualified = std::is_const<Functor>::value;
     521             :       type_result.members.type.volatile_qualified = std::is_volatile<Functor>::value;
     522             :       get_vtable()->manager(functor, type_result,
     523             :                       detail::function::check_functor_type_tag);
     524             :       return static_cast<Functor*>(type_result.members.obj_ptr);
     525             :     }
     526             : 
     527             :   template<typename Functor>
     528             :     const Functor* target() const
     529             :     {
     530             :       if (!vtable) return 0;
     531             : 
     532             :       detail::function::function_buffer type_result;
     533             :       type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
     534             :       type_result.members.type.const_qualified = true;
     535             :       type_result.members.type.volatile_qualified = std::is_volatile<Functor>::value;
     536             :       get_vtable()->manager(functor, type_result,
     537             :                       detail::function::check_functor_type_tag);
     538             :       // GCC 2.95.3 gets the CV qualifiers wrong here, so we
     539             :       // can't do the static_cast that we should do.
     540             :       return static_cast<const Functor*>(type_result.members.obj_ptr);
     541             :     }
     542             : 
     543             :   template<typename F>
     544             :     typename std::enable_if< !std::is_function<F>::value, bool >::type
     545             :     contains(const F& f) const
     546             :     {
     547             :       if (const F* fp = this->template target<F>())
     548             :       {
     549             :         return function_equal(*fp, f);
     550             :       } else {
     551             :         return false;
     552             :       }
     553             :     }
     554             : 
     555             :   template<typename Fn>
     556             :     typename std::enable_if< std::is_function<Fn>::value, bool >::type
     557             :     contains(Fn& f) const
     558             :     {
     559             :       typedef Fn* F;
     560             :       if (const F* fp = this->template target<F>())
     561             :       {
     562             :         return function_equal(*fp, &f);
     563             :       } else {
     564             :         return false;
     565             :       }
     566             :     }
     567             : 
     568             : public: // should be protected, but GCC 2.95.3 will fail to allow access
     569             :   detail::function::vtable_base* get_vtable() const {
     570             :     return reinterpret_cast<detail::function::vtable_base*>(
     571             :              reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
     572             :   }
     573             : 
     574      209364 :   bool has_trivial_copy_and_destroy() const {
     575      209364 :     return reinterpret_cast<std::size_t>(vtable) & 0x01;
     576             :   }
     577             : 
     578             :   detail::function::vtable_base* vtable;
     579             :   mutable detail::function::function_buffer functor;
     580             : };
     581             : 
     582             : #if defined(BOOST_CLANG)
     583             : #   pragma clang diagnostic push
     584             : #   pragma clang diagnostic ignored "-Wweak-vtables"
     585             : #endif
     586             : /**
     587             :  * The bad_function_call exception class is thrown when a boost::function
     588             :  * object is invoked
     589             :  */
     590             : class BOOST_SYMBOL_VISIBLE bad_function_call : public std::runtime_error
     591             : {
     592             : public:
     593           0 :   bad_function_call() : std::runtime_error("call to empty boost::function") {}
     594             : };
     595             : #if defined(BOOST_CLANG)
     596             : #   pragma clang diagnostic pop
     597             : #endif
     598             : 
     599             : inline bool operator==(const function_base& f,
     600             :                        detail::function::useless_clear_type*)
     601             : {
     602             :   return f.empty();
     603             : }
     604             : 
     605             : inline bool operator!=(const function_base& f,
     606             :                        detail::function::useless_clear_type*)
     607             : {
     608             :   return !f.empty();
     609             : }
     610             : 
     611             : inline bool operator==(detail::function::useless_clear_type*,
     612             :                        const function_base& f)
     613             : {
     614             :   return f.empty();
     615             : }
     616             : 
     617             : inline bool operator!=(detail::function::useless_clear_type*,
     618             :                        const function_base& f)
     619             : {
     620             :   return !f.empty();
     621             : }
     622             : 
     623             : // Comparisons between boost::function objects and arbitrary function
     624             : // objects.
     625             : 
     626             : template<typename Functor>
     627             :   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
     628             :   operator==(const function_base& f, Functor g)
     629             :   {
     630             :     if (const Functor* fp = f.template target<Functor>())
     631             :       return function_equal(*fp, g);
     632             :     else return false;
     633             :   }
     634             : 
     635             : template<typename Functor>
     636             :   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
     637             :   operator==(Functor g, const function_base& f)
     638             :   {
     639             :     if (const Functor* fp = f.template target<Functor>())
     640             :       return function_equal(g, *fp);
     641             :     else return false;
     642             :   }
     643             : 
     644             : template<typename Functor>
     645             :   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
     646             :   operator!=(const function_base& f, Functor g)
     647             :   {
     648             :     if (const Functor* fp = f.template target<Functor>())
     649             :       return !function_equal(*fp, g);
     650             :     else return true;
     651             :   }
     652             : 
     653             : template<typename Functor>
     654             :   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
     655             :   operator!=(Functor g, const function_base& f)
     656             :   {
     657             :     if (const Functor* fp = f.template target<Functor>())
     658             :       return !function_equal(g, *fp);
     659             :     else return true;
     660             :   }
     661             : 
     662             : template<typename Functor>
     663             :   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
     664             :   operator==(const function_base& f, reference_wrapper<Functor> g)
     665             :   {
     666             :     if (const Functor* fp = f.template target<Functor>())
     667             :       return fp == g.get_pointer();
     668             :     else return false;
     669             :   }
     670             : 
     671             : template<typename Functor>
     672             :   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
     673             :   operator==(reference_wrapper<Functor> g, const function_base& f)
     674             :   {
     675             :     if (const Functor* fp = f.template target<Functor>())
     676             :       return g.get_pointer() == fp;
     677             :     else return false;
     678             :   }
     679             : 
     680             : template<typename Functor>
     681             :   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
     682             :   operator!=(const function_base& f, reference_wrapper<Functor> g)
     683             :   {
     684             :     if (const Functor* fp = f.template target<Functor>())
     685             :       return fp != g.get_pointer();
     686             :     else return true;
     687             :   }
     688             : 
     689             : template<typename Functor>
     690             :   BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
     691             :   operator!=(reference_wrapper<Functor> g, const function_base& f)
     692             :   {
     693             :     if (const Functor* fp = f.template target<Functor>())
     694             :       return g.get_pointer() != fp;
     695             :     else return true;
     696             :   }
     697             : 
     698             : namespace detail {
     699             :   namespace function {
     700             :     inline bool has_empty_target(const function_base* f)
     701             :     {
     702             :       return f->empty();
     703             :     }
     704             : 
     705             : #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
     706             :     inline bool has_empty_target(const void*)
     707             :     {
     708             :       return false;
     709             :     }
     710             : #else
     711        2757 :     inline bool has_empty_target(...)
     712             :     {
     713        2757 :       return false;
     714             :     }
     715             : #endif
     716             :   } // end namespace function
     717             : } // end namespace detail
     718             : } // end namespace boost
     719             : 
     720             : #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
     721             : 
     722             : #if defined(BOOST_MSVC)
     723             : #   pragma warning( pop )
     724             : #endif
     725             : 
     726             : #endif // BOOST_FUNCTION_BASE_HEADER

Generated by: LCOV version 1.16