123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738 |
- // Boost.Function library
- // Copyright Douglas Gregor 2001-2006
- // Copyright Emil Dotchevski 2007
- // Use, modification and distribution is subject to the Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt or copy at
- // http://www.boost.org/LICENSE_1_0.txt)
- // For more information, see http://www.boost.org
- #ifndef BOOST_FUNCTION_BASE_HEADER
- #define BOOST_FUNCTION_BASE_HEADER
- #include <boost/function/function_fwd.hpp>
- #include <boost/function_equal.hpp>
- #include <boost/core/typeinfo.hpp>
- #include <boost/core/ref.hpp>
- #include <boost/type_traits/has_trivial_copy.hpp>
- #include <boost/type_traits/has_trivial_destructor.hpp>
- #include <boost/type_traits/is_const.hpp>
- #include <boost/type_traits/is_integral.hpp>
- #include <boost/type_traits/is_volatile.hpp>
- #include <boost/type_traits/composite_traits.hpp>
- #include <boost/type_traits/conditional.hpp>
- #include <boost/type_traits/alignment_of.hpp>
- #include <boost/type_traits/enable_if.hpp>
- #include <boost/type_traits/integral_constant.hpp>
- #include <boost/type_traits/is_function.hpp>
- #include <boost/assert.hpp>
- #include <boost/config.hpp>
- #include <boost/config/workaround.hpp>
- #include <stdexcept>
- #include <string>
- #include <memory>
- #include <new>
- #if defined(BOOST_MSVC)
- # pragma warning( push )
- # pragma warning( disable : 4793 ) // complaint about native code generation
- # pragma warning( disable : 4127 ) // "conditional expression is constant"
- #endif
- // retained because used in a test
- #define BOOST_FUNCTION_TARGET_FIX(x)
- # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
- typename ::boost::enable_if_< \
- !(::boost::is_integral<Functor>::value), \
- Type>::type
- namespace boost {
- namespace detail {
- namespace function {
- class X;
- /**
- * A buffer used to store small function objects in
- * boost::function. It is a union containing function pointers,
- * object pointers, and a structure that resembles a bound
- * member function pointer.
- */
- union function_buffer_members
- {
- // For pointers to function objects
- typedef void* obj_ptr_t;
- mutable obj_ptr_t obj_ptr;
- // For pointers to std::type_info objects
- struct type_t {
- // (get_functor_type_tag, check_functor_type_tag).
- const boost::core::typeinfo* type;
- // Whether the type is const-qualified.
- bool const_qualified;
- // Whether the type is volatile-qualified.
- bool volatile_qualified;
- } type;
- // For function pointers of all kinds
- typedef void (*func_ptr_t)();
- mutable func_ptr_t func_ptr;
- #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
- # pragma warning(push)
- # pragma warning(disable: 5243)
- #endif
- // For bound member pointers
- struct bound_memfunc_ptr_t {
- void (X::*memfunc_ptr)(int);
- void* obj_ptr;
- } bound_memfunc_ptr;
- #if defined(BOOST_MSVC) && BOOST_MSVC >= 1929
- # pragma warning(pop)
- #endif
- // For references to function objects. We explicitly keep
- // track of the cv-qualifiers on the object referenced.
- struct obj_ref_t {
- mutable void* obj_ptr;
- bool is_const_qualified;
- bool is_volatile_qualified;
- } obj_ref;
- };
- union BOOST_SYMBOL_VISIBLE function_buffer
- {
- // Type-specific union members
- mutable function_buffer_members members;
- // To relax aliasing constraints
- mutable char data[sizeof(function_buffer_members)];
- };
- // The operation type to perform on the given functor/function pointer
- enum functor_manager_operation_type {
- clone_functor_tag,
- move_functor_tag,
- destroy_functor_tag,
- check_functor_type_tag,
- get_functor_type_tag
- };
- // Tags used to decide between different types of functions
- struct function_ptr_tag {};
- struct function_obj_tag {};
- struct member_ptr_tag {};
- struct function_obj_ref_tag {};
- template<typename F>
- class get_function_tag
- {
- typedef typename conditional<(is_pointer<F>::value),
- function_ptr_tag,
- function_obj_tag>::type ptr_or_obj_tag;
- typedef typename conditional<(is_member_pointer<F>::value),
- member_ptr_tag,
- ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag;
- typedef typename conditional<(is_reference_wrapper<F>::value),
- function_obj_ref_tag,
- ptr_or_obj_or_mem_tag>::type or_ref_tag;
- public:
- typedef or_ref_tag type;
- };
- // The trivial manager does nothing but return the same pointer (if we
- // are cloning) or return the null pointer (if we are deleting).
- template<typename F>
- struct reference_manager
- {
- static inline void
- manage(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
- {
- switch (op) {
- case clone_functor_tag:
- out_buffer.members.obj_ref = in_buffer.members.obj_ref;
- return;
- case move_functor_tag:
- out_buffer.members.obj_ref = in_buffer.members.obj_ref;
- in_buffer.members.obj_ref.obj_ptr = 0;
- return;
- case destroy_functor_tag:
- out_buffer.members.obj_ref.obj_ptr = 0;
- return;
- case check_functor_type_tag:
- {
- // Check whether we have the same type. We can add
- // cv-qualifiers, but we can't take them away.
- if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(F)
- && (!in_buffer.members.obj_ref.is_const_qualified
- || out_buffer.members.type.const_qualified)
- && (!in_buffer.members.obj_ref.is_volatile_qualified
- || out_buffer.members.type.volatile_qualified))
- out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
- else
- out_buffer.members.obj_ptr = 0;
- }
- return;
- case get_functor_type_tag:
- out_buffer.members.type.type = &BOOST_CORE_TYPEID(F);
- out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
- out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
- return;
- }
- }
- };
- /**
- * Determine if boost::function can use the small-object
- * optimization with the function object type F.
- */
- template<typename F>
- struct function_allows_small_object_optimization
- {
- BOOST_STATIC_CONSTANT
- (bool,
- value = ((sizeof(F) <= sizeof(function_buffer) &&
- (alignment_of<function_buffer>::value
- % alignment_of<F>::value == 0))));
- };
- template <typename F,typename A>
- struct functor_wrapper: public F, public A
- {
- functor_wrapper( F f, A a ):
- F(f),
- A(a)
- {
- }
- functor_wrapper(const functor_wrapper& f) :
- F(static_cast<const F&>(f)),
- A(static_cast<const A&>(f))
- {
- }
- };
- /**
- * The functor_manager class contains a static function "manage" which
- * can clone or destroy the given function/function object pointer.
- */
- template<typename Functor>
- struct functor_manager_common
- {
- typedef Functor functor_type;
- // Function pointers
- static inline void
- manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
- {
- if (op == clone_functor_tag)
- out_buffer.members.func_ptr = in_buffer.members.func_ptr;
- else if (op == move_functor_tag) {
- out_buffer.members.func_ptr = in_buffer.members.func_ptr;
- in_buffer.members.func_ptr = 0;
- } else if (op == destroy_functor_tag)
- out_buffer.members.func_ptr = 0;
- else if (op == check_functor_type_tag) {
- if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
- out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
- else
- out_buffer.members.obj_ptr = 0;
- } else /* op == get_functor_type_tag */ {
- out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
- out_buffer.members.type.const_qualified = false;
- out_buffer.members.type.volatile_qualified = false;
- }
- }
- // Function objects that fit in the small-object buffer.
- static inline void
- manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
- {
- if (op == clone_functor_tag) {
- const functor_type* in_functor =
- reinterpret_cast<const functor_type*>(in_buffer.data);
- new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
- } else if (op == move_functor_tag) {
- functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data);
- new (reinterpret_cast<void*>(out_buffer.data)) functor_type(std::move(*f));
- f->~Functor();
- } else if (op == destroy_functor_tag) {
- // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
- functor_type* f = reinterpret_cast<functor_type*>(out_buffer.data);
- (void)f; // suppress warning about the value of f not being used (MSVC)
- f->~Functor();
- } else if (op == check_functor_type_tag) {
- if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
- out_buffer.members.obj_ptr = in_buffer.data;
- else
- out_buffer.members.obj_ptr = 0;
- } else /* op == get_functor_type_tag */ {
- out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
- out_buffer.members.type.const_qualified = false;
- out_buffer.members.type.volatile_qualified = false;
- }
- }
- };
- template<typename Functor>
- struct functor_manager
- {
- private:
- typedef Functor functor_type;
- // Function pointers
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, function_ptr_tag)
- {
- functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
- }
- // Function objects that fit in the small-object buffer.
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, true_type)
- {
- functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
- }
- // Function objects that require heap allocation
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, false_type)
- {
- if (op == clone_functor_tag) {
- // Clone the functor
- // GCC 2.95.3 gets the CV qualifiers wrong here, so we
- // can't do the static_cast that we should do.
- // jewillco: Changing this to static_cast because GCC 2.95.3 is
- // obsolete.
- const functor_type* f =
- static_cast<const functor_type*>(in_buffer.members.obj_ptr);
- functor_type* new_f = new functor_type(*f);
- out_buffer.members.obj_ptr = new_f;
- } else if (op == move_functor_tag) {
- out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
- in_buffer.members.obj_ptr = 0;
- } else if (op == destroy_functor_tag) {
- /* Cast from the void pointer to the functor pointer type */
- functor_type* f =
- static_cast<functor_type*>(out_buffer.members.obj_ptr);
- delete f;
- out_buffer.members.obj_ptr = 0;
- } else if (op == check_functor_type_tag) {
- if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
- out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
- else
- out_buffer.members.obj_ptr = 0;
- } else /* op == get_functor_type_tag */ {
- out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
- out_buffer.members.type.const_qualified = false;
- out_buffer.members.type.volatile_qualified = false;
- }
- }
- // For function objects, we determine whether the function
- // object can use the small-object optimization buffer or
- // whether we need to allocate it on the heap.
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, function_obj_tag)
- {
- manager(in_buffer, out_buffer, op,
- integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
- }
- // For member pointers, we use the small-object optimization buffer.
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, member_ptr_tag)
- {
- manager(in_buffer, out_buffer, op, true_type());
- }
- public:
- /* Dispatch to an appropriate manager based on whether we have a
- function pointer or a function object pointer. */
- static inline void
- manage(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
- {
- typedef typename get_function_tag<functor_type>::type tag_type;
- if (op == get_functor_type_tag) {
- out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
- out_buffer.members.type.const_qualified = false;
- out_buffer.members.type.volatile_qualified = false;
- } else {
- manager(in_buffer, out_buffer, op, tag_type());
- }
- }
- };
- template<typename Functor, typename Allocator>
- struct functor_manager_a
- {
- private:
- typedef Functor functor_type;
- // Function pointers
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, function_ptr_tag)
- {
- functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
- }
- // Function objects that fit in the small-object buffer.
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, true_type)
- {
- functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
- }
- // Function objects that require heap allocation
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, false_type)
- {
- typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
- using wrapper_allocator_type = typename std::allocator_traits<Allocator>::template rebind_alloc<functor_wrapper_type>;
- using wrapper_allocator_pointer_type = typename std::allocator_traits<wrapper_allocator_type>::pointer;
- if (op == clone_functor_tag) {
- // Clone the functor
- // GCC 2.95.3 gets the CV qualifiers wrong here, so we
- // can't do the static_cast that we should do.
- const functor_wrapper_type* f =
- static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
- wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
- wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
- std::allocator_traits<wrapper_allocator_type>::construct(wrapper_allocator, copy, *f);
- // Get back to the original pointer type
- functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
- out_buffer.members.obj_ptr = new_f;
- } else if (op == move_functor_tag) {
- out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
- in_buffer.members.obj_ptr = 0;
- } else if (op == destroy_functor_tag) {
- /* Cast from the void pointer to the functor_wrapper_type */
- functor_wrapper_type* victim =
- static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
- wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
- std::allocator_traits<wrapper_allocator_type>::destroy(wrapper_allocator, victim);
- wrapper_allocator.deallocate(victim,1);
- out_buffer.members.obj_ptr = 0;
- } else if (op == check_functor_type_tag) {
- if (*out_buffer.members.type.type == BOOST_CORE_TYPEID(Functor))
- out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
- else
- out_buffer.members.obj_ptr = 0;
- } else /* op == get_functor_type_tag */ {
- out_buffer.members.type.type = &BOOST_CORE_TYPEID(Functor);
- out_buffer.members.type.const_qualified = false;
- out_buffer.members.type.volatile_qualified = false;
- }
- }
- // For function objects, we determine whether the function
- // object can use the small-object optimization buffer or
- // whether we need to allocate it on the heap.
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, function_obj_tag)
- {
- manager(in_buffer, out_buffer, op,
- integral_constant<bool, (function_allows_small_object_optimization<functor_type>::value)>());
- }
- public:
- /* Dispatch to an appropriate manager based on whether we have a
- function pointer or a function object pointer. */
- static inline void
- manage(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
- {
- typedef typename get_function_tag<functor_type>::type tag_type;
- if (op == get_functor_type_tag) {
- out_buffer.members.type.type = &BOOST_CORE_TYPEID(functor_type);
- out_buffer.members.type.const_qualified = false;
- out_buffer.members.type.volatile_qualified = false;
- } else {
- manager(in_buffer, out_buffer, op, tag_type());
- }
- }
- };
- // A type that is only used for comparisons against zero
- struct useless_clear_type {};
- /**
- * Stores the "manager" portion of the vtable for a
- * boost::function object.
- */
- struct vtable_base
- {
- void (*manager)(const function_buffer& in_buffer,
- function_buffer& out_buffer,
- functor_manager_operation_type op);
- };
- } // end namespace function
- } // end namespace detail
- /**
- * The function_base class contains the basic elements needed for the
- * function1, function2, function3, etc. classes. It is common to all
- * functions (and as such can be used to tell if we have one of the
- * functionN objects).
- */
- class function_base
- {
- public:
- function_base() : vtable(0) { }
- /** Determine if the function is empty (i.e., has no target). */
- bool empty() const { return !vtable; }
- /** Retrieve the type of the stored function object, or type_id<void>()
- if this is empty. */
- const boost::core::typeinfo& target_type() const
- {
- if (!vtable) return BOOST_CORE_TYPEID(void);
- detail::function::function_buffer type;
- get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
- return *type.members.type.type;
- }
- template<typename Functor>
- Functor* target()
- {
- if (!vtable) return 0;
- detail::function::function_buffer type_result;
- type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
- type_result.members.type.const_qualified = is_const<Functor>::value;
- type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
- get_vtable()->manager(functor, type_result,
- detail::function::check_functor_type_tag);
- return static_cast<Functor*>(type_result.members.obj_ptr);
- }
- template<typename Functor>
- const Functor* target() const
- {
- if (!vtable) return 0;
- detail::function::function_buffer type_result;
- type_result.members.type.type = &BOOST_CORE_TYPEID(Functor);
- type_result.members.type.const_qualified = true;
- type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
- get_vtable()->manager(functor, type_result,
- detail::function::check_functor_type_tag);
- // GCC 2.95.3 gets the CV qualifiers wrong here, so we
- // can't do the static_cast that we should do.
- return static_cast<const Functor*>(type_result.members.obj_ptr);
- }
- template<typename F>
- typename boost::enable_if_< !boost::is_function<F>::value, bool >::type
- contains(const F& f) const
- {
- if (const F* fp = this->template target<F>())
- {
- return function_equal(*fp, f);
- } else {
- return false;
- }
- }
- template<typename Fn>
- typename boost::enable_if_< boost::is_function<Fn>::value, bool >::type
- contains(Fn& f) const
- {
- typedef Fn* F;
- if (const F* fp = this->template target<F>())
- {
- return function_equal(*fp, &f);
- } else {
- return false;
- }
- }
- public: // should be protected, but GCC 2.95.3 will fail to allow access
- detail::function::vtable_base* get_vtable() const {
- return reinterpret_cast<detail::function::vtable_base*>(
- reinterpret_cast<std::size_t>(vtable) & ~static_cast<std::size_t>(0x01));
- }
- bool has_trivial_copy_and_destroy() const {
- return reinterpret_cast<std::size_t>(vtable) & 0x01;
- }
- detail::function::vtable_base* vtable;
- mutable detail::function::function_buffer functor;
- };
- #if defined(BOOST_CLANG)
- # pragma clang diagnostic push
- # pragma clang diagnostic ignored "-Wweak-vtables"
- #endif
- /**
- * The bad_function_call exception class is thrown when a boost::function
- * object is invoked
- */
- class BOOST_SYMBOL_VISIBLE bad_function_call : public std::runtime_error
- {
- public:
- bad_function_call() : std::runtime_error("call to empty boost::function") {}
- };
- #if defined(BOOST_CLANG)
- # pragma clang diagnostic pop
- #endif
- inline bool operator==(const function_base& f,
- detail::function::useless_clear_type*)
- {
- return f.empty();
- }
- inline bool operator!=(const function_base& f,
- detail::function::useless_clear_type*)
- {
- return !f.empty();
- }
- inline bool operator==(detail::function::useless_clear_type*,
- const function_base& f)
- {
- return f.empty();
- }
- inline bool operator!=(detail::function::useless_clear_type*,
- const function_base& f)
- {
- return !f.empty();
- }
- // Comparisons between boost::function objects and arbitrary function
- // objects.
- template<typename Functor>
- BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
- operator==(const function_base& f, Functor g)
- {
- if (const Functor* fp = f.template target<Functor>())
- return function_equal(*fp, g);
- else return false;
- }
- template<typename Functor>
- BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
- operator==(Functor g, const function_base& f)
- {
- if (const Functor* fp = f.template target<Functor>())
- return function_equal(g, *fp);
- else return false;
- }
- template<typename Functor>
- BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
- operator!=(const function_base& f, Functor g)
- {
- if (const Functor* fp = f.template target<Functor>())
- return !function_equal(*fp, g);
- else return true;
- }
- template<typename Functor>
- BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
- operator!=(Functor g, const function_base& f)
- {
- if (const Functor* fp = f.template target<Functor>())
- return !function_equal(g, *fp);
- else return true;
- }
- template<typename Functor>
- BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
- operator==(const function_base& f, reference_wrapper<Functor> g)
- {
- if (const Functor* fp = f.template target<Functor>())
- return fp == g.get_pointer();
- else return false;
- }
- template<typename Functor>
- BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
- operator==(reference_wrapper<Functor> g, const function_base& f)
- {
- if (const Functor* fp = f.template target<Functor>())
- return g.get_pointer() == fp;
- else return false;
- }
- template<typename Functor>
- BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
- operator!=(const function_base& f, reference_wrapper<Functor> g)
- {
- if (const Functor* fp = f.template target<Functor>())
- return fp != g.get_pointer();
- else return true;
- }
- template<typename Functor>
- BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool)
- operator!=(reference_wrapper<Functor> g, const function_base& f)
- {
- if (const Functor* fp = f.template target<Functor>())
- return g.get_pointer() != fp;
- else return true;
- }
- namespace detail {
- namespace function {
- inline bool has_empty_target(const function_base* f)
- {
- return f->empty();
- }
- #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
- inline bool has_empty_target(const void*)
- {
- return false;
- }
- #else
- inline bool has_empty_target(...)
- {
- return false;
- }
- #endif
- } // end namespace function
- } // end namespace detail
- } // end namespace boost
- #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
- #if defined(BOOST_MSVC)
- # pragma warning( pop )
- #endif
- #endif // BOOST_FUNCTION_BASE_HEADER
|