// Boost.Function library
-// Copyright Douglas Gregor 2001-2006. Use, modification and
-// distribution is subject to the Boost Software License, Version
-// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// 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
#endif
#include <boost/function_equal.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
+
+// Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
+#ifdef BOOST_NO_EXCEPTION_STD_NAMESPACE
+// Embedded VC++ does not have type_info in namespace std
+# define BOOST_FUNCTION_STD_NS
+#else
+# define BOOST_FUNCTION_STD_NS std
+#endif
+
// Borrowed from Boost.Python library: determines the cases where we
// need to use std::type_info::name to compare instead of operator==.
# if (defined(__GNUC__) && __GNUC__ >= 3) \
#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
namespace boost {
-#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
-// The library shipping with MIPSpro 7.3.1.3m has a broken allocator<void>
-class function_base;
-
-template<typename Signature,
- typename Allocator = std::allocator<function_base> >
-class function;
-#else
-template<typename Signature, typename Allocator = std::allocator<void> >
+template<typename Signature>
class function;
-#endif
-template<typename Signature, typename Allocator>
-inline void swap(function<Signature, Allocator>& f1,
- function<Signature, Allocator>& f2)
+template<typename Signature>
+inline void swap(function<Signature>& f1,
+ function<Signature>& f2)
{
f1.swap(f2);
}
// DPG TBD: Since we're only storing a pointer, it's
// possible that the user could ask for a base class or
// derived class. Is that okay?
- const std::type_info& check_type =
- *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
+ const BOOST_FUNCTION_STD_NS::type_info& check_type =
+ *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else
% 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)
+ {
+ }
+ };
+
/**
* The functor_manager class contains a static function "manage" which
* can clone or destroy the given function/function object pointer.
*/
- template<typename Functor, typename Allocator>
- struct functor_manager
+ template<typename Functor>
+ struct functor_manager_common
{
- private:
typedef Functor functor_type;
- // For function pointers, the manager is trivial
+ // Function pointers
static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, function_ptr_tag)
+ manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op)
{
if (op == clone_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr;
else if (op == destroy_functor_tag)
out_buffer.func_ptr = 0;
else /* op == check_functor_type_tag */ {
- const std::type_info& check_type =
- *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
+ const BOOST_FUNCTION_STD_NS::type_info& check_type =
+ *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = &in_buffer.func_ptr;
else
// 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_)
+ 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 =
// Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
} else /* op == check_functor_type_tag */ {
- const std::type_info& check_type =
- *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
+ const BOOST_FUNCTION_STD_NS::type_info& check_type =
+ *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = &in_buffer.data;
else
out_buffer.obj_ptr = 0;
}
}
+ };
+
+ 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_)
{
-#ifndef BOOST_NO_STD_ALLOCATOR
- typedef typename Allocator::template rebind<functor_type>::other
- allocator_type;
- typedef typename allocator_type::pointer pointer_type;
-#else
- typedef functor_type* pointer_type;
-#endif // BOOST_NO_STD_ALLOCATOR
-
-# ifndef BOOST_NO_STD_ALLOCATOR
- allocator_type allocator;
-# endif // BOOST_NO_STD_ALLOCATOR
-
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_type* f =
(const functor_type*)(in_buffer.obj_ptr);
-
- // Clone the functor
-# ifndef BOOST_NO_STD_ALLOCATOR
- pointer_type copy = allocator.allocate(1);
- allocator.construct(copy, *f);
-
- // Get back to the original pointer type
- functor_type* new_f = static_cast<functor_type*>(copy);
-# else
functor_type* new_f = new functor_type(*f);
-# endif // BOOST_NO_STD_ALLOCATOR
out_buffer.obj_ptr = new_f;
} 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.obj_ptr);
+ delete f;
+ out_buffer.obj_ptr = 0;
+ } else /* op == check_functor_type_tag */ {
+ const BOOST_FUNCTION_STD_NS::type_info& check_type =
+ *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
+ if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
+ out_buffer.obj_ptr = in_buffer.obj_ptr;
+ else
+ out_buffer.obj_ptr = 0;
+ }
+ }
+
+ // 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.const_obj_ptr = &typeid(functor_type);
+ return;
-# ifndef BOOST_NO_STD_ALLOCATOR
- /* Cast from the functor pointer type to the allocator's pointer
- type */
- pointer_type victim = static_cast<pointer_type>(f);
+ default:
+ manager(in_buffer, out_buffer, op, tag_type());
+ return;
+ }
+ }
+ };
- // Destroy and deallocate the functor
- allocator.destroy(victim);
- allocator.deallocate(victim, 1);
-# else
- delete f;
-# endif // BOOST_NO_STD_ALLOCATOR
+ 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 =
+ (const functor_wrapper_type*)(in_buffer.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.obj_ptr = new_f;
+ } 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.obj_ptr);
+ wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
+ wrapper_allocator.destroy(victim);
+ wrapper_allocator.deallocate(victim,1);
out_buffer.obj_ptr = 0;
} else /* op == check_functor_type_tag */ {
- const std::type_info& check_type =
- *static_cast<const std::type_info*>(out_buffer.const_obj_ptr);
+ const BOOST_FUNCTION_STD_NS::type_info& check_type =
+ *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
out_buffer.obj_ptr = in_buffer.obj_ptr;
else
/** Retrieve the type of the stored function object, or typeid(void)
if this is empty. */
- const std::type_info& target_type() const
+ const BOOST_FUNCTION_STD_NS::type_info& target_type() const
{
if (!vtable) return typeid(void);
detail::function::function_buffer type;
vtable->manager(functor, type, detail::function::get_functor_type_tag);
- return *static_cast<const std::type_info*>(type.const_obj_ptr);
+ return *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(type.const_obj_ptr);
}
template<typename Functor>