LCOV - code coverage report
Current view: top level - usr/include/boost/function - function_base.hpp (source / functions) Hit Total Coverage
Test: ROSE Lines: 0 55 0.0 %
Date: 2022-12-08 13:48:47 Functions: 0 5 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14