867 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
		
		
			
		
	
	
			867 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
|   | // 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 <stdexcept> | ||
|  | #include <string> | ||
|  | #include <memory> | ||
|  | #include <new> | ||
|  | #include <boost/config.hpp> | ||
|  | #include <boost/assert.hpp> | ||
|  | #include <boost/integer.hpp> | ||
|  | #include <boost/type_index.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/ref.hpp> | ||
|  | #include <boost/mpl/if.hpp> | ||
|  | #include <boost/detail/workaround.hpp> | ||
|  | #include <boost/type_traits/alignment_of.hpp> | ||
|  | #ifndef BOOST_NO_SFINAE | ||
|  | #  include "boost/utility/enable_if.hpp" | ||
|  | #else | ||
|  | #  include "boost/mpl/bool.hpp" | ||
|  | #endif | ||
|  | #include <boost/function_equal.hpp> | ||
|  | #include <boost/function/function_fwd.hpp> | ||
|  | 
 | ||
|  | #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 | ||
|  | 
 | ||
|  | #if defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG) | ||
|  | #  define BOOST_FUNCTION_TARGET_FIX(x) x | ||
|  | #else | ||
|  | #  define BOOST_FUNCTION_TARGET_FIX(x) | ||
|  | #endif // __ICL etc | ||
|  | 
 | ||
|  | #  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)              \ | ||
|  |       typename ::boost::enable_if_c<          \ | ||
|  |                            !(::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::typeindex::type_info* 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; | ||
|  | 
 | ||
|  |         // For bound member pointers | ||
|  |         struct bound_memfunc_ptr_t { | ||
|  |           void (X::*memfunc_ptr)(int); | ||
|  |           void* obj_ptr; | ||
|  |         } bound_memfunc_ptr; | ||
|  | 
 | ||
|  |         // 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 function_buffer | ||
|  |       { | ||
|  |         // Type-specific union members | ||
|  |         mutable function_buffer_members members; | ||
|  | 
 | ||
|  |         // To relax aliasing constraints | ||
|  |         mutable char data[sizeof(function_buffer_members)]; | ||
|  |       }; | ||
|  | 
 | ||
|  |       /** | ||
|  |        * The unusable class is a placeholder for unused function arguments | ||
|  |        * It is also completely unusable except that it constructable from | ||
|  |        * anything. This helps compilers without partial specialization to | ||
|  |        * handle Boost.Function objects returning void. | ||
|  |        */ | ||
|  |       struct unusable | ||
|  |       { | ||
|  |         unusable() {} | ||
|  |         template<typename T> unusable(const T&) {} | ||
|  |       }; | ||
|  | 
 | ||
|  |       /* Determine the return type. This supports compilers that do not support | ||
|  |        * void returns or partial specialization by silently changing the return | ||
|  |        * type to "unusable". | ||
|  |        */ | ||
|  |       template<typename T> struct function_return_type { typedef T type; }; | ||
|  | 
 | ||
|  |       template<> | ||
|  |       struct function_return_type<void> | ||
|  |       { | ||
|  |         typedef unusable type; | ||
|  |       }; | ||
|  | 
 | ||
|  |       // 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 mpl::if_c<(is_pointer<F>::value), | ||
|  |                                    function_ptr_tag, | ||
|  |                                    function_obj_tag>::type ptr_or_obj_tag; | ||
|  | 
 | ||
|  |         typedef typename mpl::if_c<(is_member_pointer<F>::value), | ||
|  |                                    member_ptr_tag, | ||
|  |                                    ptr_or_obj_tag>::type ptr_or_obj_or_mem_tag; | ||
|  | 
 | ||
|  |         typedef typename mpl::if_c<(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::typeindex::type_id<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::typeindex::type_id<F>().type_info(); | ||
|  |             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::typeindex::type_id<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::typeindex::type_id<Functor>().type_info(); | ||
|  |             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 || op == move_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); | ||
|  | 
 | ||
|  |             if (op == move_functor_tag) { | ||
|  |               functor_type* f = reinterpret_cast<functor_type*>(in_buffer.data); | ||
|  |               (void)f; // suppress warning about the value of f not being used (MSVC) | ||
|  |               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::typeindex::type_id<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::typeindex::type_id<Functor>().type_info(); | ||
|  |             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, mpl::true_) | ||
|  |         { | ||
|  |           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, mpl::false_) | ||
|  |         { | ||
|  |           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::typeindex::type_id<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::typeindex::type_id<Functor>().type_info(); | ||
|  |             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, | ||
|  |                   mpl::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, mpl::true_()); | ||
|  |         } | ||
|  | 
 | ||
|  |       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; | ||
|  |           switch (op) { | ||
|  |           case get_functor_type_tag: | ||
|  |             out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info(); | ||
|  |             out_buffer.members.type.const_qualified = false; | ||
|  |             out_buffer.members.type.volatile_qualified = false; | ||
|  |             return; | ||
|  | 
 | ||
|  |           default: | ||
|  |             manager(in_buffer, out_buffer, op, tag_type()); | ||
|  |             return; | ||
|  |           } | ||
|  |         } | ||
|  |       }; | ||
|  | 
 | ||
|  |       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, mpl::true_) | ||
|  |         { | ||
|  |           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, mpl::false_) | ||
|  |         { | ||
|  |           typedef functor_wrapper<Functor,Allocator> functor_wrapper_type; | ||
|  |           typedef typename Allocator::template rebind<functor_wrapper_type>::other | ||
|  |             wrapper_allocator_type; | ||
|  |           typedef typename wrapper_allocator_type::pointer wrapper_allocator_pointer_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. | ||
|  |             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); | ||
|  |             wrapper_allocator.construct(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)); | ||
|  |             wrapper_allocator.destroy(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::typeindex::type_id<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::typeindex::type_id<Functor>().type_info(); | ||
|  |             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, | ||
|  |                   mpl::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; | ||
|  |           switch (op) { | ||
|  |           case get_functor_type_tag: | ||
|  |             out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info(); | ||
|  |             out_buffer.members.type.const_qualified = false; | ||
|  |             out_buffer.members.type.volatile_qualified = false; | ||
|  |             return; | ||
|  | 
 | ||
|  |           default: | ||
|  |             manager(in_buffer, out_buffer, op, tag_type()); | ||
|  |             return; | ||
|  |           } | ||
|  |         } | ||
|  |       }; | ||
|  | 
 | ||
|  |       // A type that is only used for comparisons against zero | ||
|  |       struct useless_clear_type {}; | ||
|  | 
 | ||
|  | #ifdef BOOST_NO_SFINAE | ||
|  |       // These routines perform comparisons between a Boost.Function | ||
|  |       // object and an arbitrary function object (when the last | ||
|  |       // parameter is mpl::bool_<false>) or against zero (when the | ||
|  |       // last parameter is mpl::bool_<true>). They are only necessary | ||
|  |       // for compilers that don't support SFINAE. | ||
|  |       template<typename Function, typename Functor> | ||
|  |         bool | ||
|  |         compare_equal(const Function& f, const Functor&, int, mpl::bool_<true>) | ||
|  |         { return f.empty(); } | ||
|  | 
 | ||
|  |       template<typename Function, typename Functor> | ||
|  |         bool | ||
|  |         compare_not_equal(const Function& f, const Functor&, int, | ||
|  |                           mpl::bool_<true>) | ||
|  |         { return !f.empty(); } | ||
|  | 
 | ||
|  |       template<typename Function, typename Functor> | ||
|  |         bool | ||
|  |         compare_equal(const Function& f, const Functor& g, long, | ||
|  |                       mpl::bool_<false>) | ||
|  |         { | ||
|  |           if (const Functor* fp = f.template target<Functor>()) | ||
|  |             return function_equal(*fp, g); | ||
|  |           else return false; | ||
|  |         } | ||
|  | 
 | ||
|  |       template<typename Function, typename Functor> | ||
|  |         bool | ||
|  |         compare_equal(const Function& f, const reference_wrapper<Functor>& g, | ||
|  |                       int, mpl::bool_<false>) | ||
|  |         { | ||
|  |           if (const Functor* fp = f.template target<Functor>()) | ||
|  |             return fp == g.get_pointer(); | ||
|  |           else return false; | ||
|  |         } | ||
|  | 
 | ||
|  |       template<typename Function, typename Functor> | ||
|  |         bool | ||
|  |         compare_not_equal(const Function& f, const Functor& g, long, | ||
|  |                           mpl::bool_<false>) | ||
|  |         { | ||
|  |           if (const Functor* fp = f.template target<Functor>()) | ||
|  |             return !function_equal(*fp, g); | ||
|  |           else return true; | ||
|  |         } | ||
|  | 
 | ||
|  |       template<typename Function, typename Functor> | ||
|  |         bool | ||
|  |         compare_not_equal(const Function& f, | ||
|  |                           const reference_wrapper<Functor>& g, int, | ||
|  |                           mpl::bool_<false>) | ||
|  |         { | ||
|  |           if (const Functor* fp = f.template target<Functor>()) | ||
|  |             return fp != g.get_pointer(); | ||
|  |           else return true; | ||
|  |         } | ||
|  | #endif // BOOST_NO_SFINAE | ||
|  | 
 | ||
|  |       /** | ||
|  |        * 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::typeindex::type_info& target_type() const | ||
|  |   { | ||
|  |     if (!vtable) return boost::typeindex::type_id<void>().type_info(); | ||
|  | 
 | ||
|  |     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::typeindex::type_id<Functor>().type_info(); | ||
|  |       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::typeindex::type_id<Functor>().type_info(); | ||
|  |       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> | ||
|  |     bool contains(const F& f) const | ||
|  |     { | ||
|  |       if (const F* fp = this->template target<F>()) | ||
|  |       { | ||
|  |         return function_equal(*fp, f); | ||
|  |       } else { | ||
|  |         return false; | ||
|  |       } | ||
|  |     } | ||
|  | 
 | ||
|  | #if defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3 | ||
|  |   // GCC 3.3 and newer cannot copy with the global operator==, due to | ||
|  |   // problems with instantiation of function return types before it | ||
|  |   // has been verified that the argument types match up. | ||
|  |   template<typename Functor> | ||
|  |     BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor, bool) | ||
|  |     operator==(Functor g) const | ||
|  |     { | ||
|  |       if (const Functor* fp = 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 | ||
|  |     { | ||
|  |       if (const Functor* fp = target<Functor>()) | ||
|  |         return !function_equal(*fp, g); | ||
|  |       else return true; | ||
|  |     } | ||
|  | #endif | ||
|  | 
 | ||
|  | 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; | ||
|  | }; | ||
|  | 
 | ||
|  | /** | ||
|  |  * The bad_function_call exception class is thrown when a boost::function | ||
|  |  * object is invoked | ||
|  |  */ | ||
|  | class bad_function_call : public std::runtime_error | ||
|  | { | ||
|  | public: | ||
|  |   bad_function_call() : std::runtime_error("call to empty boost::function") {} | ||
|  | }; | ||
|  | 
 | ||
|  | #ifndef BOOST_NO_SFINAE | ||
|  | 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(); | ||
|  | } | ||
|  | #endif | ||
|  | 
 | ||
|  | #ifdef BOOST_NO_SFINAE | ||
|  | // Comparisons between boost::function objects and arbitrary function objects | ||
|  | template<typename Functor> | ||
|  |   inline bool operator==(const function_base& f, Functor g) | ||
|  |   { | ||
|  |     typedef mpl::bool_<(is_integral<Functor>::value)> integral; | ||
|  |     return detail::function::compare_equal(f, g, 0, integral()); | ||
|  |   } | ||
|  | 
 | ||
|  | template<typename Functor> | ||
|  |   inline bool operator==(Functor g, const function_base& f) | ||
|  |   { | ||
|  |     typedef mpl::bool_<(is_integral<Functor>::value)> integral; | ||
|  |     return detail::function::compare_equal(f, g, 0, integral()); | ||
|  |   } | ||
|  | 
 | ||
|  | template<typename Functor> | ||
|  |   inline bool operator!=(const function_base& f, Functor g) | ||
|  |   { | ||
|  |     typedef mpl::bool_<(is_integral<Functor>::value)> integral; | ||
|  |     return detail::function::compare_not_equal(f, g, 0, integral()); | ||
|  |   } | ||
|  | 
 | ||
|  | template<typename Functor> | ||
|  |   inline bool operator!=(Functor g, const function_base& f) | ||
|  |   { | ||
|  |     typedef mpl::bool_<(is_integral<Functor>::value)> integral; | ||
|  |     return detail::function::compare_not_equal(f, g, 0, integral()); | ||
|  |   } | ||
|  | #else | ||
|  | 
 | ||
|  | #  if !(defined(__GNUC__) && __GNUC__ == 3 && __GNUC_MINOR__ <= 3) | ||
|  | // Comparisons between boost::function objects and arbitrary function | ||
|  | // objects. GCC 3.3 and before has an obnoxious bug that prevents this | ||
|  | // from working. | ||
|  | 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; | ||
|  |   } | ||
|  | #  endif | ||
|  | 
 | ||
|  | 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; | ||
|  |   } | ||
|  | 
 | ||
|  | #endif // Compiler supporting SFINAE | ||
|  | 
 | ||
|  | 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 |