sl@0: // Boost.Function library sl@0: sl@0: // Copyright Douglas Gregor 2001-2006. Use, modification and sl@0: // distribution is subject to the Boost Software License, Version sl@0: // 1.0. (See accompanying file LICENSE_1_0.txt or copy at sl@0: // http://www.boost.org/LICENSE_1_0.txt) sl@0: sl@0: // For more information, see http://www.boost.org sl@0: sl@0: #ifndef BOOST_FUNCTION_BASE_HEADER sl@0: #define BOOST_FUNCTION_BASE_HEADER sl@0: sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #include sl@0: #ifndef BOOST_NO_SFINAE sl@0: # include "boost/utility/enable_if.hpp" sl@0: #else sl@0: # include "boost/mpl/bool.hpp" sl@0: #endif sl@0: #include sl@0: sl@0: // Borrowed from Boost.Python library: determines the cases where we sl@0: // need to use std::type_info::name to compare instead of operator==. sl@0: # if (defined(__GNUC__) && __GNUC__ >= 3) \ sl@0: || defined(_AIX) \ sl@0: || ( defined(__sgi) && defined(__host_mips)) sl@0: # include sl@0: # define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) \ sl@0: (std::strcmp((X).name(),(Y).name()) == 0) sl@0: # else sl@0: # define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y)) sl@0: #endif sl@0: sl@0: #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG) sl@0: # define BOOST_FUNCTION_TARGET_FIX(x) x sl@0: #else sl@0: # define BOOST_FUNCTION_TARGET_FIX(x) sl@0: #endif // not MSVC sl@0: sl@0: #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG) sl@0: // Work around a compiler bug. sl@0: // boost::python::objects::function has to be seen by the compiler before the sl@0: // boost::function class template. sl@0: namespace boost { namespace python { namespace objects { sl@0: class function; sl@0: }}} sl@0: #endif sl@0: sl@0: #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \ sl@0: || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \ sl@0: || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540) sl@0: # define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX sl@0: #endif sl@0: sl@0: #if !BOOST_WORKAROUND(__BORLANDC__, < 0x600) sl@0: # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ sl@0: typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \ sl@0: (::boost::is_integral::value)>::value), \ sl@0: Type>::type sl@0: #else sl@0: // BCC doesn't recognize this depends on a template argument and complains sl@0: // about the use of 'typename' sl@0: # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \ sl@0: ::boost::enable_if_c<(::boost::type_traits::ice_not< \ sl@0: (::boost::is_integral::value)>::value), \ sl@0: Type>::type sl@0: #endif sl@0: sl@0: #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX) sl@0: namespace boost { sl@0: sl@0: #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG) sl@0: // The library shipping with MIPSpro 7.3.1.3m has a broken allocator sl@0: class function_base; sl@0: sl@0: template > sl@0: class function; sl@0: #else sl@0: template > sl@0: class function; sl@0: #endif sl@0: sl@0: template sl@0: inline void swap(function& f1, sl@0: function& f2) sl@0: { sl@0: f1.swap(f2); sl@0: } sl@0: sl@0: } // end namespace boost sl@0: #endif // have partial specialization sl@0: sl@0: namespace boost { sl@0: namespace detail { sl@0: namespace function { sl@0: class X; sl@0: sl@0: /** sl@0: * A buffer used to store small function objects in sl@0: * boost::function. It is a union containing function pointers, sl@0: * object pointers, and a structure that resembles a bound sl@0: * member function pointer. sl@0: */ sl@0: union function_buffer sl@0: { sl@0: // For pointers to function objects sl@0: void* obj_ptr; sl@0: sl@0: // For pointers to std::type_info objects sl@0: // (get_functor_type_tag, check_functor_type_tag). sl@0: const void* const_obj_ptr; sl@0: sl@0: // For function pointers of all kinds sl@0: mutable void (*func_ptr)(); sl@0: sl@0: // For bound member pointers sl@0: struct bound_memfunc_ptr_t { sl@0: void (X::*memfunc_ptr)(int); sl@0: void* obj_ptr; sl@0: } bound_memfunc_ptr; sl@0: sl@0: // To relax aliasing constraints sl@0: mutable char data; sl@0: }; sl@0: sl@0: /** sl@0: * The unusable class is a placeholder for unused function arguments sl@0: * It is also completely unusable except that it constructable from sl@0: * anything. This helps compilers without partial specialization to sl@0: * handle Boost.Function objects returning void. sl@0: */ sl@0: struct unusable sl@0: { sl@0: unusable() {} sl@0: template unusable(const T&) {} sl@0: }; sl@0: sl@0: /* Determine the return type. This supports compilers that do not support sl@0: * void returns or partial specialization by silently changing the return sl@0: * type to "unusable". sl@0: */ sl@0: template struct function_return_type { typedef T type; }; sl@0: sl@0: template<> sl@0: struct function_return_type sl@0: { sl@0: typedef unusable type; sl@0: }; sl@0: sl@0: // The operation type to perform on the given functor/function pointer sl@0: enum functor_manager_operation_type { sl@0: clone_functor_tag, sl@0: destroy_functor_tag, sl@0: check_functor_type_tag, sl@0: get_functor_type_tag sl@0: }; sl@0: sl@0: // Tags used to decide between different types of functions sl@0: struct function_ptr_tag {}; sl@0: struct function_obj_tag {}; sl@0: struct member_ptr_tag {}; sl@0: struct function_obj_ref_tag {}; sl@0: sl@0: template sl@0: class get_function_tag sl@0: { sl@0: typedef typename mpl::if_c<(is_pointer::value), sl@0: function_ptr_tag, sl@0: function_obj_tag>::type ptr_or_obj_tag; sl@0: sl@0: typedef typename mpl::if_c<(is_member_pointer::value), sl@0: member_ptr_tag, sl@0: ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag; sl@0: sl@0: typedef typename mpl::if_c<(is_reference_wrapper::value), sl@0: function_obj_ref_tag, sl@0: ptr_or_obj_or_mem_tag>::type or_ref_tag; sl@0: sl@0: public: sl@0: typedef or_ref_tag type; sl@0: }; sl@0: sl@0: // The trivial manager does nothing but return the same pointer (if we sl@0: // are cloning) or return the null pointer (if we are deleting). sl@0: template sl@0: struct reference_manager sl@0: { sl@0: static inline void sl@0: get(const function_buffer& in_buffer, function_buffer& out_buffer, sl@0: functor_manager_operation_type op) sl@0: { sl@0: switch (op) { sl@0: case clone_functor_tag: sl@0: out_buffer.obj_ptr = in_buffer.obj_ptr; sl@0: return; sl@0: sl@0: case destroy_functor_tag: sl@0: out_buffer.obj_ptr = 0; sl@0: return; sl@0: sl@0: case check_functor_type_tag: sl@0: { sl@0: // DPG TBD: Since we're only storing a pointer, it's sl@0: // possible that the user could ask for a base class or sl@0: // derived class. Is that okay? sl@0: const std::type_info& check_type = sl@0: *static_cast(out_buffer.const_obj_ptr); sl@0: if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F))) sl@0: out_buffer.obj_ptr = in_buffer.obj_ptr; sl@0: else sl@0: out_buffer.obj_ptr = 0; sl@0: } sl@0: return; sl@0: sl@0: case get_functor_type_tag: sl@0: out_buffer.const_obj_ptr = &typeid(F); sl@0: return; sl@0: } sl@0: } sl@0: }; sl@0: sl@0: /** sl@0: * Determine if boost::function can use the small-object sl@0: * optimization with the function object type F. sl@0: */ sl@0: template sl@0: struct function_allows_small_object_optimization sl@0: { sl@0: BOOST_STATIC_CONSTANT sl@0: (bool, sl@0: value = ((sizeof(F) <= sizeof(function_buffer) && sl@0: (alignment_of::value sl@0: % alignment_of::value == 0)))); sl@0: }; sl@0: sl@0: /** sl@0: * The functor_manager class contains a static function "manage" which sl@0: * can clone or destroy the given function/function object pointer. sl@0: */ sl@0: template sl@0: struct functor_manager sl@0: { sl@0: private: sl@0: typedef Functor functor_type; sl@0: sl@0: // For function pointers, the manager is trivial sl@0: static inline void sl@0: manager(const function_buffer& in_buffer, function_buffer& out_buffer, sl@0: functor_manager_operation_type op, function_ptr_tag) sl@0: { sl@0: if (op == clone_functor_tag) sl@0: out_buffer.func_ptr = in_buffer.func_ptr; sl@0: else if (op == destroy_functor_tag) sl@0: out_buffer.func_ptr = 0; sl@0: else /* op == check_functor_type_tag */ { sl@0: const std::type_info& check_type = sl@0: *static_cast(out_buffer.const_obj_ptr); sl@0: if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor))) sl@0: out_buffer.obj_ptr = &in_buffer.func_ptr; sl@0: else sl@0: out_buffer.obj_ptr = 0; sl@0: } sl@0: } sl@0: sl@0: // Function objects that fit in the small-object buffer. sl@0: static inline void sl@0: manager(const function_buffer& in_buffer, function_buffer& out_buffer, sl@0: functor_manager_operation_type op, mpl::true_) sl@0: { sl@0: if (op == clone_functor_tag) { sl@0: const functor_type* in_functor = sl@0: reinterpret_cast(&in_buffer.data); sl@0: new ((void*)&out_buffer.data) functor_type(*in_functor); sl@0: } else if (op == destroy_functor_tag) { sl@0: // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type. sl@0: reinterpret_cast(&out_buffer.data)->~Functor(); sl@0: } else /* op == check_functor_type_tag */ { sl@0: const std::type_info& check_type = sl@0: *static_cast(out_buffer.const_obj_ptr); sl@0: if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor))) sl@0: out_buffer.obj_ptr = &in_buffer.data; sl@0: else sl@0: out_buffer.obj_ptr = 0; sl@0: } sl@0: } sl@0: sl@0: // Function objects that require heap allocation sl@0: static inline void sl@0: manager(const function_buffer& in_buffer, function_buffer& out_buffer, sl@0: functor_manager_operation_type op, mpl::false_) sl@0: { sl@0: #ifndef BOOST_NO_STD_ALLOCATOR sl@0: typedef typename Allocator::template rebind::other sl@0: allocator_type; sl@0: typedef typename allocator_type::pointer pointer_type; sl@0: #else sl@0: typedef functor_type* pointer_type; sl@0: #endif // BOOST_NO_STD_ALLOCATOR sl@0: sl@0: # ifndef BOOST_NO_STD_ALLOCATOR sl@0: allocator_type allocator; sl@0: # endif // BOOST_NO_STD_ALLOCATOR sl@0: sl@0: if (op == clone_functor_tag) { sl@0: // GCC 2.95.3 gets the CV qualifiers wrong here, so we sl@0: // can't do the static_cast that we should do. sl@0: const functor_type* f = sl@0: (const functor_type*)(in_buffer.obj_ptr); sl@0: sl@0: // Clone the functor sl@0: # ifndef BOOST_NO_STD_ALLOCATOR sl@0: pointer_type copy = allocator.allocate(1); sl@0: allocator.construct(copy, *f); sl@0: sl@0: // Get back to the original pointer type sl@0: functor_type* new_f = static_cast(copy); sl@0: # else sl@0: functor_type* new_f = new functor_type(*f); sl@0: # endif // BOOST_NO_STD_ALLOCATOR sl@0: out_buffer.obj_ptr = new_f; sl@0: } else if (op == destroy_functor_tag) { sl@0: /* Cast from the void pointer to the functor pointer type */ sl@0: functor_type* f = sl@0: static_cast(out_buffer.obj_ptr); sl@0: sl@0: # ifndef BOOST_NO_STD_ALLOCATOR sl@0: /* Cast from the functor pointer type to the allocator's pointer sl@0: type */ sl@0: pointer_type victim = static_cast(f); sl@0: sl@0: // Destroy and deallocate the functor sl@0: allocator.destroy(victim); sl@0: allocator.deallocate(victim, 1); sl@0: # else sl@0: delete f; sl@0: # endif // BOOST_NO_STD_ALLOCATOR sl@0: out_buffer.obj_ptr = 0; sl@0: } else /* op == check_functor_type_tag */ { sl@0: const std::type_info& check_type = sl@0: *static_cast(out_buffer.const_obj_ptr); sl@0: if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor))) sl@0: out_buffer.obj_ptr = in_buffer.obj_ptr; sl@0: else sl@0: out_buffer.obj_ptr = 0; sl@0: } sl@0: } sl@0: sl@0: // For function objects, we determine whether the function sl@0: // object can use the small-object optimization buffer or sl@0: // whether we need to allocate it on the heap. sl@0: static inline void sl@0: manager(const function_buffer& in_buffer, function_buffer& out_buffer, sl@0: functor_manager_operation_type op, function_obj_tag) sl@0: { sl@0: manager(in_buffer, out_buffer, op, sl@0: mpl::bool_<(function_allows_small_object_optimization::value)>()); sl@0: } sl@0: sl@0: public: sl@0: /* Dispatch to an appropriate manager based on whether we have a sl@0: function pointer or a function object pointer. */ sl@0: static inline void sl@0: manage(const function_buffer& in_buffer, function_buffer& out_buffer, sl@0: functor_manager_operation_type op) sl@0: { sl@0: typedef typename get_function_tag::type tag_type; sl@0: switch (op) { sl@0: case get_functor_type_tag: sl@0: out_buffer.const_obj_ptr = &typeid(functor_type); sl@0: return; sl@0: sl@0: default: sl@0: manager(in_buffer, out_buffer, op, tag_type()); sl@0: return; sl@0: } sl@0: } sl@0: }; sl@0: sl@0: // A type that is only used for comparisons against zero sl@0: struct useless_clear_type {}; sl@0: sl@0: #ifdef BOOST_NO_SFINAE sl@0: // These routines perform comparisons between a Boost.Function sl@0: // object and an arbitrary function object (when the last sl@0: // parameter is mpl::bool_) or against zero (when the sl@0: // last parameter is mpl::bool_). They are only necessary sl@0: // for compilers that don't support SFINAE. sl@0: template sl@0: bool sl@0: compare_equal(const Function& f, const Functor&, int, mpl::bool_) sl@0: { return f.empty(); } sl@0: sl@0: template sl@0: bool sl@0: compare_not_equal(const Function& f, const Functor&, int, sl@0: mpl::bool_) sl@0: { return !f.empty(); } sl@0: sl@0: template sl@0: bool sl@0: compare_equal(const Function& f, const Functor& g, long, sl@0: mpl::bool_) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return function_equal(*fp, g); sl@0: else return false; sl@0: } sl@0: sl@0: template sl@0: bool sl@0: compare_equal(const Function& f, const reference_wrapper& g, sl@0: int, mpl::bool_) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return fp == g.get_pointer(); sl@0: else return false; sl@0: } sl@0: sl@0: template sl@0: bool sl@0: compare_not_equal(const Function& f, const Functor& g, long, sl@0: mpl::bool_) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return !function_equal(*fp, g); sl@0: else return true; sl@0: } sl@0: sl@0: template sl@0: bool sl@0: compare_not_equal(const Function& f, sl@0: const reference_wrapper& g, int, sl@0: mpl::bool_) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return fp != g.get_pointer(); sl@0: else return true; sl@0: } sl@0: #endif // BOOST_NO_SFINAE sl@0: sl@0: /** sl@0: * Stores the "manager" portion of the vtable for a sl@0: * boost::function object. sl@0: */ sl@0: struct vtable_base sl@0: { sl@0: vtable_base() : manager(0) { } sl@0: void (*manager)(const function_buffer& in_buffer, sl@0: function_buffer& out_buffer, sl@0: functor_manager_operation_type op); sl@0: }; sl@0: } // end namespace function sl@0: } // end namespace detail sl@0: sl@0: /** sl@0: * The function_base class contains the basic elements needed for the sl@0: * function1, function2, function3, etc. classes. It is common to all sl@0: * functions (and as such can be used to tell if we have one of the sl@0: * functionN objects). sl@0: */ sl@0: class function_base sl@0: { sl@0: public: sl@0: function_base() : vtable(0) { } sl@0: sl@0: /** Determine if the function is empty (i.e., has no target). */ sl@0: bool empty() const { return !vtable; } sl@0: sl@0: /** Retrieve the type of the stored function object, or typeid(void) sl@0: if this is empty. */ sl@0: const std::type_info& target_type() const sl@0: { sl@0: if (!vtable) return typeid(void); sl@0: sl@0: detail::function::function_buffer type; sl@0: vtable->manager(functor, type, detail::function::get_functor_type_tag); sl@0: return *static_cast(type.const_obj_ptr); sl@0: } sl@0: sl@0: template sl@0: Functor* target() sl@0: { sl@0: if (!vtable) return 0; sl@0: sl@0: detail::function::function_buffer type_result; sl@0: type_result.const_obj_ptr = &typeid(Functor); sl@0: vtable->manager(functor, type_result, sl@0: detail::function::check_functor_type_tag); sl@0: return static_cast(type_result.obj_ptr); sl@0: } sl@0: sl@0: template sl@0: #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300) sl@0: const Functor* target( Functor * = 0 ) const sl@0: #else sl@0: const Functor* target() const sl@0: #endif sl@0: { sl@0: if (!vtable) return 0; sl@0: sl@0: detail::function::function_buffer type_result; sl@0: type_result.const_obj_ptr = &typeid(Functor); sl@0: vtable->manager(functor, type_result, sl@0: detail::function::check_functor_type_tag); sl@0: // GCC 2.95.3 gets the CV qualifiers wrong here, so we sl@0: // can't do the static_cast that we should do. sl@0: return (const Functor*)(type_result.obj_ptr); sl@0: } sl@0: sl@0: template sl@0: bool contains(const F& f) const sl@0: { sl@0: #if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300) sl@0: if (const F* fp = this->target( (F*)0 )) sl@0: #else sl@0: if (const F* fp = this->template target()) sl@0: #endif sl@0: { sl@0: return function_equal(*fp, f); sl@0: } else { sl@0: return false; sl@0: } sl@0: } sl@0: sl@0: #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3 sl@0: // GCC 3.3 and newer cannot copy with the global operator==, due to sl@0: // problems with instantiation of function return types before it sl@0: // has been verified that the argument types match up. sl@0: template sl@0: BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) sl@0: operator==(Functor g) const sl@0: { sl@0: if (const Functor* fp = target()) sl@0: return function_equal(*fp, g); sl@0: else return false; sl@0: } sl@0: sl@0: template sl@0: BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) sl@0: operator!=(Functor g) const sl@0: { sl@0: if (const Functor* fp = target()) sl@0: return !function_equal(*fp, g); sl@0: else return true; sl@0: } sl@0: #endif sl@0: sl@0: public: // should be protected, but GCC 2.95.3 will fail to allow access sl@0: detail::function::vtable_base* vtable; sl@0: mutable detail::function::function_buffer functor; sl@0: }; sl@0: sl@0: /** sl@0: * The bad_function_call exception class is thrown when a boost::function sl@0: * object is invoked sl@0: */ sl@0: class bad_function_call : public std::runtime_error sl@0: { sl@0: public: sl@0: bad_function_call() : std::runtime_error("call to empty boost::function") {} sl@0: }; sl@0: sl@0: #ifndef BOOST_NO_SFINAE sl@0: inline bool operator==(const function_base& f, sl@0: detail::function::useless_clear_type*) sl@0: { sl@0: return f.empty(); sl@0: } sl@0: sl@0: inline bool operator!=(const function_base& f, sl@0: detail::function::useless_clear_type*) sl@0: { sl@0: return !f.empty(); sl@0: } sl@0: sl@0: inline bool operator==(detail::function::useless_clear_type*, sl@0: const function_base& f) sl@0: { sl@0: return f.empty(); sl@0: } sl@0: sl@0: inline bool operator!=(detail::function::useless_clear_type*, sl@0: const function_base& f) sl@0: { sl@0: return !f.empty(); sl@0: } sl@0: #endif sl@0: sl@0: #ifdef BOOST_NO_SFINAE sl@0: // Comparisons between boost::function objects and arbitrary function objects sl@0: template sl@0: inline bool operator==(const function_base& f, Functor g) sl@0: { sl@0: typedef mpl::bool_<(is_integral::value)> integral; sl@0: return detail::function::compare_equal(f, g, 0, integral()); sl@0: } sl@0: sl@0: template sl@0: inline bool operator==(Functor g, const function_base& f) sl@0: { sl@0: typedef mpl::bool_<(is_integral::value)> integral; sl@0: return detail::function::compare_equal(f, g, 0, integral()); sl@0: } sl@0: sl@0: template sl@0: inline bool operator!=(const function_base& f, Functor g) sl@0: { sl@0: typedef mpl::bool_<(is_integral::value)> integral; sl@0: return detail::function::compare_not_equal(f, g, 0, integral()); sl@0: } sl@0: sl@0: template sl@0: inline bool operator!=(Functor g, const function_base& f) sl@0: { sl@0: typedef mpl::bool_<(is_integral::value)> integral; sl@0: return detail::function::compare_not_equal(f, g, 0, integral()); sl@0: } sl@0: #else sl@0: sl@0: # if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) sl@0: // Comparisons between boost::function objects and arbitrary function sl@0: // objects. GCC 3.3 and before has an obnoxious bug that prevents this sl@0: // from working. sl@0: template sl@0: BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) sl@0: operator==(const function_base& f, Functor g) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return function_equal(*fp, g); sl@0: else return false; sl@0: } sl@0: sl@0: template sl@0: BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) sl@0: operator==(Functor g, const function_base& f) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return function_equal(g, *fp); sl@0: else return false; sl@0: } sl@0: sl@0: template sl@0: BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) sl@0: operator!=(const function_base& f, Functor g) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return !function_equal(*fp, g); sl@0: else return true; sl@0: } sl@0: sl@0: template sl@0: BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) sl@0: operator!=(Functor g, const function_base& f) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return !function_equal(g, *fp); sl@0: else return true; sl@0: } sl@0: # endif sl@0: sl@0: template sl@0: BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) sl@0: operator==(const function_base& f, reference_wrapper g) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return fp == g.get_pointer(); sl@0: else return false; sl@0: } sl@0: sl@0: template sl@0: BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) sl@0: operator==(reference_wrapper g, const function_base& f) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return g.get_pointer() == fp; sl@0: else return false; sl@0: } sl@0: sl@0: template sl@0: BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) sl@0: operator!=(const function_base& f, reference_wrapper g) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return fp != g.get_pointer(); sl@0: else return true; sl@0: } sl@0: sl@0: template sl@0: BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) sl@0: operator!=(reference_wrapper g, const function_base& f) sl@0: { sl@0: if (const Functor* fp = f.template target()) sl@0: return g.get_pointer() != fp; sl@0: else return true; sl@0: } sl@0: sl@0: #endif // Compiler supporting SFINAE sl@0: sl@0: namespace detail { sl@0: namespace function { sl@0: inline bool has_empty_target(const function_base* f) sl@0: { sl@0: return f->empty(); sl@0: } sl@0: sl@0: #if BOOST_WORKAROUND(BOOST_MSVC, <= 1310) sl@0: inline bool has_empty_target(const void*) sl@0: { sl@0: return false; sl@0: } sl@0: #else sl@0: inline bool has_empty_target(...) sl@0: { sl@0: return false; sl@0: } sl@0: #endif sl@0: } // end namespace function sl@0: } // end namespace detail sl@0: } // end namespace boost sl@0: sl@0: #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL sl@0: #undef BOOST_FUNCTION_COMPARE_TYPE_ID sl@0: sl@0: #endif // BOOST_FUNCTION_BASE_HEADER