Boost logo

Boost-Commit :

From: dgregor_at_[hidden]
Date: 2008-03-27 15:44:37


Author: dgregor
Date: 2008-03-27 15:44:37 EDT (Thu, 27 Mar 2008)
New Revision: 43884
URL: http://svn.boost.org/trac/boost/changeset/43884

Log:
Change Boost.Function allocator behavior, from Emil Dotchevski
Text files modified:
   trunk/boost/function/function_base.hpp | 212 ++++++++++-----
   trunk/boost/function/function_template.hpp | 550 +++++++++++++++++++--------------------
   trunk/libs/function/doc/history.xml | 16 +
   trunk/libs/function/doc/reference.xml | 118 ++++----
   trunk/libs/function/test/allocator_test.cpp | 61 +++
   5 files changed, 533 insertions(+), 424 deletions(-)

Modified: trunk/boost/function/function_base.hpp
==============================================================================
--- trunk/boost/function/function_base.hpp (original)
+++ trunk/boost/function/function_base.hpp 2008-03-27 15:44:37 EDT (Thu, 27 Mar 2008)
@@ -1,8 +1,9 @@
 // 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
@@ -73,7 +74,7 @@
 
 #if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
  || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
- || !(defined(BOOST_STRICT_CONFIG) || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
+ || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
 # define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
 #endif
 
@@ -94,21 +95,12 @@
 #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);
 }
@@ -212,8 +204,8 @@
       struct reference_manager
       {
         static inline void
- manage(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
+ get(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op)
         {
           switch (op) {
           case clone_functor_tag:
@@ -259,20 +251,29 @@
                       % 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;
@@ -290,8 +291,8 @@
 
         // 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 =
@@ -309,57 +310,48 @@
               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);
-
-# 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);
-
- // Destroy and deallocate the functor
- allocator.destroy(victim);
- allocator.deallocate(victim, 1);
-# else
             delete f;
-# endif // BOOST_NO_STD_ALLOCATOR
             out_buffer.obj_ptr = 0;
           } else /* op == check_functor_type_tag */ {
             const BOOST_FUNCTION_STD_NS::type_info& check_type =
@@ -382,13 +374,98 @@
                   mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
         }
 
- // For member pointers, we treat them as function objects with
- // the small-object optimization always enabled.
+ 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;
+
+ 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, member_ptr_tag)
+ functor_manager_operation_type op, mpl::true_)
         {
- manager(in_buffer, out_buffer, 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<wrapper_allocator_type 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<wrapper_allocator_type const &>(*victim));
+ wrapper_allocator.destroy(victim);
+ wrapper_allocator.deallocate(victim,1);
+ 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:
@@ -479,6 +556,7 @@
        */
       struct vtable_base
       {
+ vtable_base() : manager(0) { }
         void (*manager)(const function_buffer& in_buffer,
                         function_buffer& out_buffer,
                         functor_manager_operation_type op);
@@ -580,7 +658,7 @@
 #endif
 
 public: // should be protected, but GCC 2.95.3 will fail to allow access
- const detail::function::vtable_base* vtable;
+ detail::function::vtable_base* vtable;
   mutable detail::function::function_buffer functor;
 };
 
@@ -755,8 +833,4 @@
 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
 #undef BOOST_FUNCTION_COMPARE_TYPE_ID
 
-#if defined(BOOST_MSVC)
-# pragma warning( pop )
-#endif
-
 #endif // BOOST_FUNCTION_BASE_HEADER

Modified: trunk/boost/function/function_template.hpp
==============================================================================
--- trunk/boost/function/function_template.hpp (original)
+++ trunk/boost/function/function_template.hpp 2008-03-27 15:44:37 EDT (Thu, 27 Mar 2008)
@@ -1,8 +1,9 @@
 // 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
@@ -31,13 +32,6 @@
 
 #define BOOST_FUNCTION_ARG_TYPES BOOST_PP_REPEAT(BOOST_FUNCTION_NUM_ARGS,BOOST_FUNCTION_ARG_TYPE,BOOST_PP_EMPTY)
 
-// Type of the default allocator
-#ifndef BOOST_NO_STD_ALLOCATOR
-# define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator<function_base>
-#else
-# define BOOST_FUNCTION_DEFAULT_ALLOCATOR int
-#endif // BOOST_NO_STD_ALLOCATOR
-
 // Comma if nonzero number of arguments
 #if BOOST_FUNCTION_NUM_ARGS == 0
 # define BOOST_FUNCTION_COMMA
@@ -59,20 +53,12 @@
   BOOST_JOIN(function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
 #define BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER \
   BOOST_JOIN(void_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
-#define BOOST_FUNCTION_MEMBER_INVOKER \
- BOOST_JOIN(member_invoker,BOOST_FUNCTION_NUM_ARGS)
-#define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
- BOOST_JOIN(void_member_invoker,BOOST_FUNCTION_NUM_ARGS)
 #define BOOST_FUNCTION_GET_FUNCTION_INVOKER \
   BOOST_JOIN(get_function_invoker,BOOST_FUNCTION_NUM_ARGS)
 #define BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER \
   BOOST_JOIN(get_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
 #define BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER \
   BOOST_JOIN(get_function_ref_invoker,BOOST_FUNCTION_NUM_ARGS)
-#define BOOST_FUNCTION_GET_MEMBER_INVOKER \
- BOOST_JOIN(get_member_invoker,BOOST_FUNCTION_NUM_ARGS)
-#define BOOST_FUNCTION_GET_INVOKER \
- BOOST_JOIN(get_invoker,BOOST_FUNCTION_NUM_ARGS)
 #define BOOST_FUNCTION_VTABLE BOOST_JOIN(basic_vtable,BOOST_FUNCTION_NUM_ARGS)
 
 #ifndef BOOST_NO_VOID_RETURNS
@@ -194,44 +180,6 @@
         }
       };
 
-#if BOOST_FUNCTION_NUM_ARGS > 0
- /* Handle invocation of member pointers. */
- template<
- typename MemberPtr,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_MEMBER_INVOKER
- {
- static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_PARMS)
-
- {
- MemberPtr* f =
- reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
- return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
- }
- };
-
- template<
- typename MemberPtr,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_VOID_MEMBER_INVOKER
- {
- static BOOST_FUNCTION_VOID_RETURN_TYPE
- invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_PARMS)
-
- {
- MemberPtr* f =
- reinterpret_cast<MemberPtr*>(&function_obj_ptr.data);
- BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
- }
- };
-#endif
-
       template<
         typename FunctionPtr,
         typename R BOOST_FUNCTION_COMMA
@@ -295,130 +243,11 @@
>::type type;
       };
 
-#if BOOST_FUNCTION_NUM_ARGS > 0
- /* Retrieve the appropriate invoker for a member pointer. */
- template<
- typename MemberPtr,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_GET_MEMBER_INVOKER
- {
- typedef typename mpl::if_c<(is_void<R>::value),
- BOOST_FUNCTION_VOID_MEMBER_INVOKER<
- MemberPtr,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >,
- BOOST_FUNCTION_MEMBER_INVOKER<
- MemberPtr,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >
- >::type type;
- };
-#endif
-
- /* Given the tag returned by get_function_tag, retrieve the
- actual invoker that will be used for the given function
- object.
-
- Each specialization contains an "apply" nested class template
- that accepts the function object, return type, function
- argument types, and allocator. The resulting "apply" class
- contains two typedefs, "invoker_type" and "manager_type",
- which correspond to the invoker and manager types. */
- template<typename Tag>
- struct BOOST_FUNCTION_GET_INVOKER { };
-
- /* Retrieve the invoker for a function pointer. */
- template<>
- struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
- {
- template<typename FunctionPtr,
- typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
- struct apply
- {
- typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
- FunctionPtr,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- invoker_type;
-
- typedef functor_manager<FunctionPtr, Allocator> manager_type;
- };
- };
-
-#if BOOST_FUNCTION_NUM_ARGS > 0
- /* Retrieve the invoker for a member pointer. */
- template<>
- struct BOOST_FUNCTION_GET_INVOKER<member_ptr_tag>
- {
- template<typename MemberPtr,
- typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
- struct apply
- {
- typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
- MemberPtr,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- invoker_type;
-
- typedef functor_manager<MemberPtr, Allocator> manager_type;
- };
- };
-#endif
-
- /* Retrieve the invoker for a function object. */
- template<>
- struct BOOST_FUNCTION_GET_INVOKER<function_obj_tag>
- {
- template<typename FunctionObj,
- typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
- struct apply
- {
- typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
- FunctionObj,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- invoker_type;
-
- typedef functor_manager<FunctionObj, Allocator> manager_type;
- };
- };
-
- /* Retrieve the invoker for a reference to a function object. */
- template<>
- struct BOOST_FUNCTION_GET_INVOKER<function_obj_ref_tag>
- {
- template<typename RefWrapper,
- typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
- struct apply
- {
- typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
- typename RefWrapper::type,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- invoker_type;
-
- typedef reference_manager<typename RefWrapper::type> manager_type;
- };
- };
-
       /**
        * vtable for a specific boost::function instance.
        */
- template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
- struct BOOST_FUNCTION_VTABLE
+ template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
+ struct BOOST_FUNCTION_VTABLE : vtable_base
       {
 #ifndef BOOST_NO_VOID_RETURNS
         typedef R result_type;
@@ -431,25 +260,80 @@
                                             BOOST_FUNCTION_TEMPLATE_ARGS);
 
         template<typename F>
- bool assign_to(const F& f, function_buffer& functor) const
+ BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0)
+ {
+ init(f);
+ }
+ template<typename F,typename Allocator>
+ BOOST_FUNCTION_VTABLE(F f, Allocator) : vtable_base(), invoker(0)
+ {
+ init_a<Allocator>(f);
+ }
+
+ template<typename F>
+ bool assign_to(F f, function_buffer& functor)
         {
           typedef typename get_function_tag<F>::type tag;
           return assign_to(f, functor, tag());
         }
+ template<typename F,typename Allocator>
+ bool assign_to_a(F f, function_buffer& functor, Allocator a)
+ {
+ typedef typename get_function_tag<F>::type tag;
+ return assign_to_a(f, functor, a, tag());
+ }
 
- void clear(function_buffer& functor) const
+ void clear(function_buffer& functor)
         {
- if (base.manager)
- base.manager(functor, functor, destroy_functor_tag);
+ if (manager)
+ manager(functor, functor, destroy_functor_tag);
         }
-#ifndef BOOST_NO_PRIVATE_IN_AGGREGATE
+
       private:
-#endif
+ template<typename F>
+ void init(F f)
+ {
+ typedef typename get_function_tag<F>::type tag;
+ init(f, tag());
+ }
+ template<typename Allocator,typename F>
+ void init_a(F f)
+ {
+ typedef typename get_function_tag<F>::type tag;
+ init_a<Allocator>(f, tag());
+ }
+
         // Function pointers
         template<typename FunctionPtr>
+ void init(FunctionPtr /*f*/, function_ptr_tag)
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
+ FunctionPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ actual_invoker_type;
+
+ invoker = &actual_invoker_type::invoke;
+ manager = &functor_manager<FunctionPtr>::manage;
+ }
+ template<typename Allocator,typename FunctionPtr>
+ void init_a(FunctionPtr f, function_ptr_tag)
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
+ FunctionPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ actual_invoker_type;
+
+ invoker = &actual_invoker_type::invoke;
+ manager = &functor_manager_a<FunctionPtr, Allocator>::manage;
+ }
+
+ template<typename FunctionPtr>
         bool
- assign_to(FunctionPtr f, function_buffer& functor,
- function_ptr_tag) const
+ assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
         {
           this->clear(functor);
           if (f) {
@@ -461,17 +345,53 @@
             return false;
           }
         }
+ template<typename FunctionPtr,typename Allocator>
+ bool
+ assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag)
+ {
+ return assign_to(f,functor,function_ptr_tag());
+ }
 
         // Member pointers
 #if BOOST_FUNCTION_NUM_ARGS > 0
         template<typename MemberPtr>
- bool
- assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag) const
+ void init(MemberPtr f, member_ptr_tag)
         {
+ // DPG TBD: Add explicit support for member function
+ // objects, so we invoke through mem_fn() but we retain the
+ // right target_type() values.
+ this->init(mem_fn(f));
+ }
+ template<typename Allocator,typename MemberPtr>
+ void init_a(MemberPtr f, member_ptr_tag)
+ {
+ // DPG TBD: Add explicit support for member function
+ // objects, so we invoke through mem_fn() but we retain the
+ // right target_type() values.
+ this->init_a<Allocator>(mem_fn(f));
+ }
+
+ template<typename MemberPtr>
+ bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag)
+ {
+ // DPG TBD: Add explicit support for member function
+ // objects, so we invoke through mem_fn() but we retain the
+ // right target_type() values.
+ if (f) {
+ this->assign_to(mem_fn(f), functor);
+ return true;
+ } else {
+ return false;
+ }
+ }
+ template<typename MemberPtr,typename Allocator>
+ bool assign_to_a(MemberPtr f, function_buffer& functor, Allocator a, member_ptr_tag)
+ {
+ // DPG TBD: Add explicit support for member function
+ // objects, so we invoke through mem_fn() but we retain the
+ // right target_type() values.
           if (f) {
- // Always use the small-object optimization for member
- // pointers.
- assign_functor(f, functor, mpl::true_());
+ this->assign_to_a(mem_fn(f), functor, a);
             return true;
           } else {
             return false;
@@ -480,41 +400,72 @@
 #endif // BOOST_FUNCTION_NUM_ARGS > 0
 
         // Function objects
+ template<typename FunctionObj>
+ void init(FunctionObj /*f*/, function_obj_tag)
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
+ FunctionObj,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ actual_invoker_type;
+
+ invoker = &actual_invoker_type::invoke;
+ manager = &functor_manager<FunctionObj>::manage;
+ }
+ template<typename Allocator,typename FunctionObj>
+ void init_a(FunctionObj /*f*/, function_obj_tag)
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
+ FunctionObj,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ actual_invoker_type;
+
+ invoker = &actual_invoker_type::invoke;
+ manager = &functor_manager_a<FunctionObj, Allocator>::manage;
+ }
+
         // Assign to a function object using the small object optimization
         template<typename FunctionObj>
         void
- assign_functor(const FunctionObj& f, function_buffer& functor,
- mpl::true_) const
+ assign_functor(FunctionObj f, function_buffer& functor, mpl::true_)
         {
           new ((void*)&functor.data) FunctionObj(f);
         }
+ template<typename FunctionObj,typename Allocator>
+ void
+ assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_)
+ {
+ assign_functor(f,functor,mpl::true_());
+ }
 
         // Assign to a function object allocated on the heap.
         template<typename FunctionObj>
         void
- assign_functor(const FunctionObj& f, function_buffer& functor,
- mpl::false_) const
+ assign_functor(FunctionObj f, function_buffer& functor, mpl::false_)
         {
-#ifndef BOOST_NO_STD_ALLOCATOR
- typedef typename Allocator::template rebind<FunctionObj>::other
- allocator_type;
- typedef typename allocator_type::pointer pointer_type;
-
- allocator_type allocator;
- pointer_type copy = allocator.allocate(1);
- allocator.construct(copy, f);
-
- // Get back to the original pointer type
- functor.obj_ptr = static_cast<FunctionObj*>(copy);
-# else
           functor.obj_ptr = new FunctionObj(f);
-# endif // BOOST_NO_STD_ALLOCATOR
+ }
+ template<typename FunctionObj,typename Allocator>
+ void
+ assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_)
+ {
+ typedef functor_wrapper<FunctionObj,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;
+ wrapper_allocator_type wrapper_allocator(a);
+ wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
+ wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
+ functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
+ functor.obj_ptr = new_f;
         }
 
         template<typename FunctionObj>
         bool
- assign_to(const FunctionObj& f, function_buffer& functor,
- function_obj_tag) const
+ assign_to(FunctionObj f, function_buffer& functor, function_obj_tag)
         {
           if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
             assign_functor(f, functor,
@@ -524,12 +475,45 @@
             return false;
           }
         }
+ template<typename FunctionObj,typename Allocator>
+ bool
+ assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag)
+ {
+ if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
+ assign_functor_a(f, functor, a,
+ mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
+ return true;
+ } else {
+ return false;
+ }
+ }
 
         // Reference to a function object
         template<typename FunctionObj>
+ void
+ init(const reference_wrapper<FunctionObj>& /*f*/, function_obj_ref_tag)
+ {
+ typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
+ FunctionObj,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >::type
+ actual_invoker_type;
+
+ invoker = &actual_invoker_type::invoke;
+ manager = &reference_manager<FunctionObj>::get;
+ }
+ template<typename Allocator,typename FunctionObj>
+ void
+ init_a(const reference_wrapper<FunctionObj>& f, function_obj_ref_tag)
+ {
+ init(f,function_obj_ref_tag());
+ }
+
+ template<typename FunctionObj>
         bool
         assign_to(const reference_wrapper<FunctionObj>& f,
- function_buffer& functor, function_obj_ref_tag) const
+ function_buffer& functor, function_obj_ref_tag)
         {
           if (!boost::detail::function::has_empty_target(f.get_pointer())) {
             // DPG TBD: We might need to detect constness of
@@ -542,9 +526,15 @@
             return false;
           }
         }
+ template<typename FunctionObj,typename Allocator>
+ bool
+ assign_to_a(const reference_wrapper<FunctionObj>& f,
+ function_buffer& functor, Allocator, function_obj_ref_tag)
+ {
+ return assign_to(f,functor,function_obj_ref_tag());
+ }
 
       public:
- vtable_base base;
         invoker_type invoker;
       };
     } // end namespace function
@@ -552,8 +542,7 @@
 
   template<
     typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR
+ BOOST_FUNCTION_TEMPLATE_PARMS
>
   class BOOST_FUNCTION_FUNCTION : public function_base
 
@@ -578,7 +567,7 @@
 
   private:
     typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
- R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, Allocator>
+ R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
       vtable_type;
 
     struct clear_type {};
@@ -603,7 +592,6 @@
     BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
     BOOST_FUNCTION_ARG_TYPES
 
- typedef Allocator allocator_type;
     typedef BOOST_FUNCTION_FUNCTION self_type;
 
     BOOST_FUNCTION_FUNCTION() : function_base() { }
@@ -623,6 +611,19 @@
     {
       this->assign_to(f);
     }
+ template<typename Functor,typename Allocator>
+ BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
+#ifndef BOOST_NO_SFINAE
+ ,typename enable_if_c<
+ (boost::type_traits::ice_not<
+ (is_integral<Functor>::value)>::value),
+ int>::type = 0
+#endif // BOOST_NO_SFINAE
+ ) :
+ function_base()
+ {
+ this->assign_to_a(f,a);
+ }
 
 #ifndef BOOST_NO_SFINAE
     BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
@@ -648,7 +649,7 @@
       if (this->empty())
         boost::throw_exception(bad_function_call());
 
- return reinterpret_cast<const vtable_type*>(vtable)->invoker
+ return static_cast<vtable_type*>(vtable)->invoker
                (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
     }
 #else
@@ -672,18 +673,25 @@
     operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
     {
       this->clear();
-#ifndef BOOST_NO_EXCEPTIONS
       try {
         this->assign_to(f);
       } catch (...) {
         vtable = 0;
         throw;
       }
-#else
- this->assign_to(f);
-#endif
       return *this;
     }
+ template<typename Functor,typename Allocator>
+ void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
+ {
+ this->clear();
+ try {
+ this->assign_to_a(f,a);
+ } catch (...) {
+ vtable = 0;
+ throw;
+ }
+ }
 
 #ifndef BOOST_NO_SFINAE
     BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
@@ -707,16 +715,12 @@
         return *this;
 
       this->clear();
-#ifndef BOOST_NO_EXCEPTIONS
       try {
         this->assign_to_own(f);
       } catch (...) {
         vtable = 0;
         throw;
       }
-#else
- this->assign_to_own(f);
-#endif
       return *this;
     }
 
@@ -734,7 +738,7 @@
     void clear()
     {
       if (vtable) {
- reinterpret_cast<const vtable_type*>(vtable)->clear(this->functor);
+ static_cast<vtable_type*>(vtable)->clear(this->functor);
         vtable = 0;
       }
     }
@@ -769,84 +773,64 @@
     }
 
     template<typename Functor>
- void assign_to(const Functor& f)
+ void assign_to(Functor f)
     {
- using detail::function::vtable_base;
-
- typedef typename detail::function::get_function_tag<Functor>::type tag;
- typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
- typedef typename get_invoker::
- template apply<Functor, R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS, Allocator>
- handler_type;
-
- typedef typename handler_type::invoker_type invoker_type;
- typedef typename handler_type::manager_type manager_type;
-
- static const vtable_type stored_vtable =
- { { &manager_type::manage }, &invoker_type::invoke };
-
- if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable.base;
+ static vtable_type stored_vtable(f);
+ if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
+ else vtable = 0;
+ }
+ template<typename Functor,typename Allocator>
+ void assign_to_a(Functor f,Allocator a)
+ {
+ static vtable_type stored_vtable(f,a);
+ if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
       else vtable = 0;
     }
   };
 
- template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
- typename Allocator>
+ template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
   inline void swap(BOOST_FUNCTION_FUNCTION<
                      R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS ,
- Allocator
+ BOOST_FUNCTION_TEMPLATE_ARGS
>& f1,
                    BOOST_FUNCTION_FUNCTION<
                      R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS,
- Allocator
+ BOOST_FUNCTION_TEMPLATE_ARGS
>& f2)
   {
     f1.swap(f2);
   }
 
 #if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
- template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
+ template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
   typename BOOST_FUNCTION_FUNCTION<
- R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
- Allocator>::result_type
- BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS,
-
- Allocator>
+ R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type
+ BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
   ::operator()(BOOST_FUNCTION_PARMS) const
   {
     if (this->empty())
       boost::throw_exception(bad_function_call());
 
- return reinterpret_cast<const vtable_type*>(vtable)->invoker
+ return static_cast<vtable_type*>(vtable)->invoker
              (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
   }
 #endif
 
 // Poison comparisons between boost::function objects of the same type.
-template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
- typename Allocator>
+template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
   void operator==(const BOOST_FUNCTION_FUNCTION<
                           R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS ,
- Allocator>&,
+ BOOST_FUNCTION_TEMPLATE_ARGS>&,
                   const BOOST_FUNCTION_FUNCTION<
                           R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS ,
- Allocator>&);
-template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS ,
- typename Allocator>
+ BOOST_FUNCTION_TEMPLATE_ARGS>&);
+template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
   void operator!=(const BOOST_FUNCTION_FUNCTION<
                           R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS ,
- Allocator>&,
+ BOOST_FUNCTION_TEMPLATE_ARGS>&,
                   const BOOST_FUNCTION_FUNCTION<
                           R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS ,
- Allocator>&);
+ BOOST_FUNCTION_TEMPLATE_ARGS>& );
 
 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
 
@@ -857,20 +841,16 @@
 #endif
 
 template<typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
-class function<BOOST_FUNCTION_PARTIAL_SPEC, Allocator>
- : public BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
- BOOST_FUNCTION_COMMA Allocator>
+ BOOST_FUNCTION_TEMPLATE_PARMS>
+class function<BOOST_FUNCTION_PARTIAL_SPEC>
+ : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
 {
- typedef BOOST_FUNCTION_FUNCTION<R, BOOST_FUNCTION_TEMPLATE_ARGS
- BOOST_FUNCTION_COMMA Allocator> base_type;
+ typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
   typedef function self_type;
 
   struct clear_type {};
 
 public:
- typedef typename base_type::allocator_type allocator_type;
 
   function() : base_type() {}
 
@@ -886,6 +866,18 @@
     base_type(f)
   {
   }
+ template<typename Functor,typename Allocator>
+ function(Functor f, Allocator a
+#ifndef BOOST_NO_SFINAE
+ ,typename enable_if_c<
+ (boost::type_traits::ice_not<
+ (is_integral<Functor>::value)>::value),
+ int>::type = 0
+#endif
+ ) :
+ base_type(f,a)
+ {
+ }
 
 #ifndef BOOST_NO_SFINAE
   function(clear_type*) : base_type() {}
@@ -938,8 +930,6 @@
 
 // Cleanup after ourselves...
 #undef BOOST_FUNCTION_VTABLE
-#undef BOOST_FUNCTION_GET_INVOKER
-#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR
 #undef BOOST_FUNCTION_COMMA
 #undef BOOST_FUNCTION_FUNCTION
 #undef BOOST_FUNCTION_FUNCTION_INVOKER
@@ -948,12 +938,10 @@
 #undef BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
 #undef BOOST_FUNCTION_FUNCTION_REF_INVOKER
 #undef BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
-#undef BOOST_FUNCTION_MEMBER_INVOKER
-#undef BOOST_FUNCTION_VOID_MEMBER_INVOKER
 #undef BOOST_FUNCTION_GET_FUNCTION_INVOKER
 #undef BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
 #undef BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
-#undef BOOST_FUNCTION_GET_MEMBER_INVOKER
+#undef BOOST_FUNCTION_GET_MEM_FUNCTION_INVOKER
 #undef BOOST_FUNCTION_TEMPLATE_PARMS
 #undef BOOST_FUNCTION_TEMPLATE_ARGS
 #undef BOOST_FUNCTION_PARMS

Modified: trunk/libs/function/doc/history.xml
==============================================================================
--- trunk/libs/function/doc/history.xml (original)
+++ trunk/libs/function/doc/history.xml 2008-03-27 15:44:37 EDT (Thu, 27 Mar 2008)
@@ -13,6 +13,22 @@
 
 <itemizedlist spacing="compact">
 
+ <listitem><para><bold>Version 1.36.0</bold>: </para>
+ <itemizedlist spacing="compact">
+ <listitem><para>Boost.Function now implements allocator support
+ in the same way that is is provided in C++0x, based on C++
+ committee
+ proposal <ulink url="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2308.html">N2308</ulink>. This
+ change removes the <computeroutput>Allocator</computeroutput>
+ template parameter of <classname>boost::function</classname> in
+ favor of a constructor that takes an argument. While this is a
+ backward-incompatible change, it is likely to affect only a few
+ users. This change to Function was contributed by Emil
+ Dotchevski, which also authored the corresponding C++ committee
+ proposal.</para></listitem>
+ </itemizedlist>
+ </listitem>
+
   <listitem><para><bold>Version 1.34.0</bold>: </para>
     <itemizedlist spacing="compact">
       <listitem><para>Boost.Function now implements a small buffer optimization, which can drastically improve the performance when copying or construction Boost.Function objects storing small function objects. For instance, <code>bind(&amp;X:foo, &amp;x, _1, _2)</code> requires no heap allocation when placed into a Boost.Function object. Note that some exception-safety guarantees have changed: assignment provides the basic exception guarantee and <code>swap()</code> may throw.</para></listitem>

Modified: trunk/libs/function/doc/reference.xml
==============================================================================
--- trunk/libs/function/doc/reference.xml (original)
+++ trunk/libs/function/doc/reference.xml 2008-03-27 15:44:37 EDT (Thu, 27 Mar 2008)
@@ -141,9 +141,6 @@
       <template-type-parameter name="T2"/>
       <template-varargs/>
       <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator">
- <default><classname>std::allocator</classname>&lt;void&gt;</default>
- </template-type-parameter>
     </template>
 
     <inherit access="public"><classname>function_base</classname></inherit>
@@ -160,7 +157,6 @@
     </description>
 
     <typedef name="result_type"><type>R</type></typedef>
- <typedef name="allocator_type"><type>Allocator</type></typedef>
     <typedef name="argument_type">
       <type>T1</type><purpose>If N == 1</purpose>
     </typedef>
@@ -216,6 +212,19 @@
       <postconditions><simpara><code>*this</code> targets a copy of <code>f</code> if <code>f</code> is nonempty, or <code>this-&gt;<methodname>empty</methodname>()</code> if <code>f</code> is empty.</simpara></postconditions>
     </constructor>
 
+ <constructor>
+ <template>
+ <template-type-parameter name="F"/>
+ <template-type-parameter name="Allocator"/>
+ </template>
+ <parameter name="f"><paramtype>F</paramtype></parameter>
+ <parameter name="alloc"><paramtype>Allocator</paramtype></parameter>
+ <requires><simpara>F is a function object Callable from <code>this</code>, Allocator is an allocator. The copy constructor and destructor of Allocator shall not throw.</simpara></requires>
+ <postconditions><simpara><code>*this</code> targets a copy of <code>f</code> if <code>f</code> is nonempty, or <code>this-&gt;<methodname>empty</methodname>()</code> if <code>f</code> is empty.</simpara></postconditions>
+
+ <effects><simpara>If memory allocation is required, the given allocator (or a copy of it) will be used to allocate that memory.</simpara></effects>
+ </constructor>
+
     <destructor>
       <effects><simpara>If <code>!this-&gt;<methodname>empty</methodname>()</code>, destroys the target of this.</simpara></effects>
 
@@ -324,11 +333,10 @@
           <template-type-parameter name="T2"/>
           <template-varargs/>
           <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator"/>
         </template>
         <type>void</type>
- <parameter name="f1"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
- <parameter name="f2"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f1"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
+ <parameter name="f2"><paramtype><classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
         <effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects>
       </function>
     </free-function-group>
@@ -341,11 +349,10 @@
             <template-type-parameter name="T2"/>
             <template-varargs/>
             <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
- <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
           <parameter name="g"><paramtype>Functor</paramtype></parameter>
         </signature>
         <signature>
@@ -354,12 +361,11 @@
             <template-type-parameter name="T2"/>
             <template-varargs/>
             <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
           <parameter name="g"><paramtype>Functor</paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
         </signature>
         <signature>
           <template>
@@ -367,11 +373,10 @@
             <template-type-parameter name="T2"/>
             <template-varargs/>
             <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
- <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
           <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
         </signature>
         <signature>
@@ -380,12 +385,11 @@
             <template-type-parameter name="T2"/>
             <template-varargs/>
             <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
           <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
         </signature>
         <signature>
           <template>
@@ -393,16 +397,14 @@
             <template-type-parameter name="T2"/>
             <template-varargs/>
             <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator1"/>
             <template-type-parameter name="U1"/>
             <template-type-parameter name="U2"/>
             <template-varargs/>
             <template-type-parameter name="UN"/>
- <template-type-parameter name="Allocator2"/>
           </template>
           <type>void</type>
- <parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter>
- <parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
+ <parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
+ <parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN&gt;&amp;</paramtype></parameter>
         </signature>
 
         <returns><simpara>True when <code>f</code> stores an object of
@@ -442,11 +444,10 @@
             <template-type-parameter name="T2"/>
             <template-varargs/>
             <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
- <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
           <parameter name="g"><paramtype>Functor</paramtype></parameter>
         </signature>
         <signature>
@@ -455,12 +456,11 @@
             <template-type-parameter name="T2"/>
             <template-varargs/>
             <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
           <parameter name="g"><paramtype>Functor</paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
         </signature>
         <signature>
           <template>
@@ -468,11 +468,10 @@
             <template-type-parameter name="T2"/>
             <template-varargs/>
             <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
- <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
           <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
         </signature>
         <signature>
@@ -481,12 +480,11 @@
             <template-type-parameter name="T2"/>
             <template-varargs/>
             <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
           <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
         </signature>
         <signature>
           <template>
@@ -494,16 +492,14 @@
             <template-type-parameter name="T2"/>
             <template-varargs/>
             <template-type-parameter name="TN"/>
- <template-type-parameter name="Allocator1"/>
             <template-type-parameter name="U1"/>
             <template-type-parameter name="U2"/>
             <template-varargs/>
             <template-type-parameter name="UN"/>
- <template-type-parameter name="Allocator2"/>
           </template>
           <type>void</type>
- <parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN, Allocator1&gt;&amp;</paramtype></parameter>
- <parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN, Allocator2&gt;&amp;</paramtype></parameter>
+ <parameter name="f1"><paramtype>const <classname>functionN</classname>&lt;T1, T2, ..., TN&gt;&amp;</paramtype></parameter>
+ <parameter name="f2"><paramtype>const <classname>functionN</classname>&lt;U1, U2, ..., UN&gt;&amp;</paramtype></parameter>
         </signature>
 
         <returns><simpara>True when <code>f</code> does not store an
@@ -543,11 +539,8 @@
       <template-type-parameter name="Signature">
         <purpose>Function type R (T1, T2, ..., TN)</purpose>
       </template-type-parameter>
- <template-type-parameter name="Allocator">
- <default><classname>std::allocator</classname>&lt;void&gt;</default>
- </template-type-parameter>
     </template>
- <inherit access="public"><classname>functionN</classname>&lt;R, T1, T2, ..., TN, Allocator&gt;</inherit>
+ <inherit access="public"><classname>functionN</classname>&lt;R, T1, T2, ..., TN&gt;</inherit>
 
     <purpose>A generalized function pointer that can be used for
     callbacks or wrapping function objects.</purpose>
@@ -569,7 +562,6 @@
     </description>
 
     <typedef name="result_type"><type>R</type></typedef>
- <typedef name="allocator_type"><type>Allocator</type></typedef>
     <typedef name="argument_type">
       <type>T1</type><purpose>If N == 1</purpose>
     </typedef>
@@ -633,6 +625,19 @@
       <postconditions><simpara><code>*this</code> targets a copy of <code>f</code> if <code>f</code> is nonempty, or <code>this-&gt;<methodname>empty</methodname>()</code> if <code>f</code> is empty.</simpara></postconditions>
     </constructor>
 
+ <constructor>
+ <template>
+ <template-type-parameter name="F"/>
+ <template-type-parameter name="Allocator"/>
+ </template>
+ <parameter name="f"><paramtype>F</paramtype></parameter>
+ <parameter name="alloc"><paramtype>Allocator</paramtype></parameter>
+ <requires><simpara>F is a function object Callable from <code>this</code>, Allocator is an allocator. The copy constructor and destructor of Allocator shall not throw.</simpara></requires>
+ <postconditions><simpara><code>*this</code> targets a copy of <code>f</code> if <code>f</code> is nonempty, or <code>this-&gt;<methodname>empty</methodname>()</code> if <code>f</code> is empty.</simpara></postconditions>
+
+ <effects><simpara>If memory allocation is required, the given allocator (or a copy of it) will be used to allocate that memory.</simpara></effects>
+ </constructor>
+
     <destructor>
       <effects><simpara>If <code>!this-&gt;<methodname>empty</methodname>()</code>, destroys the target of <code>this</code>.</simpara></effects>
 
@@ -745,11 +750,10 @@
       <function name="swap">
         <template>
           <template-type-parameter name="Signature"/>
- <template-type-parameter name="Allocator"/>
         </template>
         <type>void</type>
- <parameter name="f1"><paramtype><classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
- <parameter name="f2"><paramtype><classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f1"><paramtype><classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
+ <parameter name="f2"><paramtype><classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
         <effects><simpara><code>f1.<methodname>swap</methodname>(f2)</code></simpara></effects>
       </function>
     </free-function-group>
@@ -759,53 +763,47 @@
         <signature>
           <template>
             <template-type-parameter name="Signature"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
- <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
           <parameter name="g"><paramtype>Functor</paramtype></parameter>
         </signature>
         <signature>
           <template>
             <template-type-parameter name="Signature"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
           <parameter name="g"><paramtype>Functor</paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
         </signature>
         <signature>
           <template>
             <template-type-parameter name="Signature"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
- <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
           <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
         </signature>
         <signature>
           <template>
             <template-type-parameter name="Signature"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
           <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
         </signature>
         <signature>
           <template>
             <template-type-parameter name="Signature1"/>
- <template-type-parameter name="Allocator1"/>
             <template-type-parameter name="Signature2"/>
- <template-type-parameter name="Allocator2"/>
           </template>
           <type>void</type>
- <parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter>
- <parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
+ <parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1&gt;&amp;</paramtype></parameter>
+ <parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2&gt;&amp;</paramtype></parameter>
         </signature>
 
         <returns><simpara>True when <code>f</code> stores an object of
@@ -840,53 +838,47 @@
         <signature>
           <template>
             <template-type-parameter name="Signature"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
- <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
           <parameter name="g"><paramtype>Functor</paramtype></parameter>
         </signature>
         <signature>
           <template>
             <template-type-parameter name="Signature"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
           <parameter name="g"><paramtype>Functor</paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
         </signature>
         <signature>
           <template>
             <template-type-parameter name="Signature"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
- <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
           <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
         </signature>
         <signature>
           <template>
             <template-type-parameter name="Signature"/>
- <template-type-parameter name="Allocator"/>
             <template-type-parameter name="Functor"/>
           </template>
           <type>bool</type>
           <parameter name="g"><paramtype><classname>reference_wrapper</classname>&lt;Functor&gt;</paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature, Allocator&gt;&amp;</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname>&lt;Signature&gt;&amp;</paramtype></parameter>
         </signature>
         <signature>
           <template>
             <template-type-parameter name="Signature1"/>
- <template-type-parameter name="Allocator1"/>
             <template-type-parameter name="Signature2"/>
- <template-type-parameter name="Allocator2"/>
           </template>
           <type>void</type>
- <parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1, Allocator1&gt;&amp;</paramtype></parameter>
- <parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2, Allocator2&gt;&amp;</paramtype></parameter>
+ <parameter name="f1"><paramtype>const <classname>function</classname>&lt;Signature1&gt;&amp;</paramtype></parameter>
+ <parameter name="f2"><paramtype>const <classname>function</classname>&lt;Signature2&gt;&amp;</paramtype></parameter>
         </signature>
 
         <returns><simpara>True when <code>f</code> does not store an

Modified: trunk/libs/function/test/allocator_test.cpp
==============================================================================
--- trunk/libs/function/test/allocator_test.cpp (original)
+++ trunk/libs/function/test/allocator_test.cpp 2008-03-27 15:44:37 EDT (Thu, 27 Mar 2008)
@@ -27,6 +27,14 @@
     typedef counting_allocator<U> other;
   };
 
+ counting_allocator()
+ {
+ }
+
+ template<typename U>
+ counting_allocator( counting_allocator<U> )
+ {
+ }
 
   T* allocate(std::size_t n)
   {
@@ -41,20 +49,27 @@
   }
 };
 
-struct plus_int
+struct enable_small_object_optimization
 {
- int operator()(int x, int y) const { return x + y; }
+};
 
+struct disable_small_object_optimization
+{
   int unused_state_data[32];
 };
 
+template <typename base>
+struct plus_int: base
+{
+ int operator()(int x, int y) const { return x + y; }
+};
+
 static int do_minus(int x, int y) { return x-y; }
 
-struct DoNothing
+template <typename base>
+struct DoNothing: base
 {
   void operator()() const {}
-
- int unused_state_data[32];
 };
 
 static void do_nothing() {}
@@ -62,33 +77,57 @@
 int
 test_main(int, char*[])
 {
- function2<int, int, int, counting_allocator<int> > f;
- f = plus_int();
+ function2<int, int, int> f;
+ f.assign( plus_int<disable_small_object_optimization>(), counting_allocator<int>() );
   f.clear();
   BOOST_CHECK(alloc_count == 1);
   BOOST_CHECK(dealloc_count == 1);
+ alloc_count = 0;
+ dealloc_count = 0;
+ f.assign( plus_int<enable_small_object_optimization>(), counting_allocator<int>() );
+ f.clear();
+ BOOST_CHECK(alloc_count == 0);
+ BOOST_CHECK(dealloc_count == 0);
+ f.assign( plus_int<disable_small_object_optimization>(), std::allocator<int>() );
+ f.clear();
+ f.assign( plus_int<enable_small_object_optimization>(), std::allocator<int>() );
+ f.clear();
 
   alloc_count = 0;
   dealloc_count = 0;
- f = &do_minus;
+ f.assign( &do_minus, counting_allocator<int>() );
   f.clear();
   BOOST_CHECK(alloc_count == 0);
   BOOST_CHECK(dealloc_count == 0);
+ f.assign( &do_minus, std::allocator<int>() );
+ f.clear();
 
- function0<void, counting_allocator<int> > fv;
+ function0<void> fv;
   alloc_count = 0;
   dealloc_count = 0;
- fv = DoNothing();
+ fv.assign( DoNothing<disable_small_object_optimization>(), counting_allocator<int>() );
   fv.clear();
   BOOST_CHECK(alloc_count == 1);
   BOOST_CHECK(dealloc_count == 1);
+ alloc_count = 0;
+ dealloc_count = 0;
+ fv.assign( DoNothing<enable_small_object_optimization>(), counting_allocator<int>() );
+ fv.clear();
+ BOOST_CHECK(alloc_count == 0);
+ BOOST_CHECK(dealloc_count == 0);
+ fv.assign( DoNothing<disable_small_object_optimization>(), std::allocator<int>() );
+ fv.clear();
+ fv.assign( DoNothing<enable_small_object_optimization>(), std::allocator<int>() );
+ fv.clear();
 
   alloc_count = 0;
   dealloc_count = 0;
- fv = &do_nothing;
+ fv.assign( &do_nothing, counting_allocator<int>() );
   fv.clear();
   BOOST_CHECK(alloc_count == 0);
   BOOST_CHECK(dealloc_count == 0);
+ fv.assign( &do_nothing, std::allocator<int>() );
+ fv.clear();
 
   return 0;
 }


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk