BVB Source Codes

mars Show function_base.hpp Source code

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

 Back to top