|
Boost-Commit : |
From: dgregor_at_[hidden]
Date: 2008-07-14 14:32:30
Author: dgregor
Date: 2008-07-14 14:32:29 EDT (Mon, 14 Jul 2008)
New Revision: 47422
URL: http://svn.boost.org/trac/boost/changeset/47422
Log:
Merge Boost.Function from the trunk
Text files modified:
branches/release/boost/function/detail/prologue.hpp | 3
branches/release/boost/function/function_base.hpp | 212 ++++++++++-----
branches/release/boost/function/function_template.hpp | 550 +++++++++++++++++++--------------------
branches/release/libs/function/doc/history.xml | 16 +
branches/release/libs/function/doc/misc.xml | 6
branches/release/libs/function/doc/reference.xml | 118 ++++----
branches/release/libs/function/test/allocator_test.cpp | 61 +++
7 files changed, 538 insertions(+), 428 deletions(-)
Modified: branches/release/boost/function/detail/prologue.hpp
==============================================================================
--- branches/release/boost/function/detail/prologue.hpp (original)
+++ branches/release/boost/function/detail/prologue.hpp 2008-07-14 14:32:29 EDT (Mon, 14 Jul 2008)
@@ -11,7 +11,7 @@
#define BOOST_FUNCTION_PROLOGUE_HPP
# include <cassert>
# include <algorithm>
-# include <functional> // unary_function, binary_function
+# include <boost/config/no_tr1/functional.hpp> // unary_function, binary_function
# include <boost/throw_exception.hpp>
# include <boost/config.hpp>
# include <boost/function/function_base.hpp>
@@ -22,4 +22,5 @@
# include <boost/preprocessor/cat.hpp>
# include <boost/preprocessor/repeat.hpp>
# include <boost/preprocessor/inc.hpp>
+# include <boost/type_traits/is_void.hpp>
#endif // BOOST_FUNCTION_PROLOGUE_HPP
Modified: branches/release/boost/function/function_base.hpp
==============================================================================
--- branches/release/boost/function/function_base.hpp (original)
+++ branches/release/boost/function/function_base.hpp 2008-07-14 14:32:29 EDT (Mon, 14 Jul 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<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 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: branches/release/boost/function/function_template.hpp
==============================================================================
--- branches/release/boost/function/function_template.hpp (original)
+++ branches/release/boost/function/function_template.hpp 2008-07-14 14:32:29 EDT (Mon, 14 Jul 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: branches/release/libs/function/doc/history.xml
==============================================================================
--- branches/release/libs/function/doc/history.xml (original)
+++ branches/release/libs/function/doc/history.xml 2008-07-14 14:32:29 EDT (Mon, 14 Jul 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(&X:foo, &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: branches/release/libs/function/doc/misc.xml
==============================================================================
--- branches/release/libs/function/doc/misc.xml (original)
+++ branches/release/libs/function/doc/misc.xml 2008-07-14 14:32:29 EDT (Mon, 14 Jul 2008)
@@ -24,7 +24,7 @@
<para> And, of course, function pointers have several advantages over Boost.Function:
<itemizedlist spacing="compact">
- <listitem><para> Function pointers are smaller (the size of one pointer instead of three) </para></listitem>
+ <listitem><para> Function pointers are smaller (the size of one pointer instead of four or more) </para></listitem>
<listitem><para> Function pointers are faster (Boost.Function may require two calls through function pointers) </para></listitem>
<listitem><para> Function pointers are backward-compatible with C libraries.</para></listitem>
<listitem><para> More readable error messages. </para></listitem>
@@ -37,12 +37,12 @@
<section>
<title>Function object wrapper size</title>
-<para> Function object wrappers will be the size of two function pointers plus one function pointer or data pointer (whichever is larger). On common 32-bit platforms, this amounts to 12 bytes per wrapper. Additionally, the function object target will be allocated on the heap.</para>
+ <para> Function object wrappers will be the size of a struct containing a member function pointer and two data pointers. The actual size can vary significantly depending on the underlying platform; on 32-bit Mac OS X with GCC, this amounts to 16 bytes, while it is 32 bytes Windows with Visual C++. Additionally, the function object target may be allocated on the heap, if it cannot be placed into the small-object buffer in the <code>boost::function</code> object.</para>
</section>
<section>
<title>Copying efficiency</title>
-<para> Copying function object wrappers may require allocating memory for a copy of the function object target. The default allocator may be replaced with a faster custom allocator or one may choose to allow the function object wrappers to only store function object targets by reference (using <computeroutput>ref</computeroutput>) if the cost of this cloning becomes prohibitive.</para>
+ <para> Copying function object wrappers may require allocating memory for a copy of the function object target. The default allocator may be replaced with a faster custom allocator or one may choose to allow the function object wrappers to only store function object targets by reference (using <computeroutput>ref</computeroutput>) if the cost of this cloning becomes prohibitive. Small function objects can be stored within the <code>boost::function</code> object itself, improving copying efficiency.</para>
</section>
<section>
Modified: branches/release/libs/function/doc/reference.xml
==============================================================================
--- branches/release/libs/function/doc/reference.xml (original)
+++ branches/release/libs/function/doc/reference.xml 2008-07-14 14:32:29 EDT (Mon, 14 Jul 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><void></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-><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-><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-><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><T1, T2, ..., TN, Allocator>&</paramtype></parameter>
- <parameter name="f2"><paramtype><classname>functionN</classname><T1, T2, ..., TN, Allocator>&</paramtype></parameter>
+ <parameter name="f1"><paramtype><classname>functionN</classname><T1, T2, ..., TN>&</paramtype></parameter>
+ <parameter name="f2"><paramtype><classname>functionN</classname><T1, T2, ..., TN>&</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><T1, T2, ..., TN, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN>&</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><T1, T2, ..., TN, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN>&</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><T1, T2, ..., TN, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN>&</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname><Functor></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><Functor></paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN>&</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><T1, T2, ..., TN, Allocator1>&</paramtype></parameter>
- <parameter name="f2"><paramtype>const <classname>functionN</classname><U1, U2, ..., UN, Allocator2>&</paramtype></parameter>
+ <parameter name="f1"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN>&</paramtype></parameter>
+ <parameter name="f2"><paramtype>const <classname>functionN</classname><U1, U2, ..., UN>&</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><T1, T2, ..., TN, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN>&</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><T1, T2, ..., TN, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN>&</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><T1, T2, ..., TN, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN>&</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname><Functor></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><Functor></paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN>&</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><T1, T2, ..., TN, Allocator1>&</paramtype></parameter>
- <parameter name="f2"><paramtype>const <classname>functionN</classname><U1, U2, ..., UN, Allocator2>&</paramtype></parameter>
+ <parameter name="f1"><paramtype>const <classname>functionN</classname><T1, T2, ..., TN>&</paramtype></parameter>
+ <parameter name="f2"><paramtype>const <classname>functionN</classname><U1, U2, ..., UN>&</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><void></default>
- </template-type-parameter>
</template>
- <inherit access="public"><classname>functionN</classname><R, T1, T2, ..., TN, Allocator></inherit>
+ <inherit access="public"><classname>functionN</classname><R, T1, T2, ..., TN></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-><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-><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-><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><Signature, Allocator>&</paramtype></parameter>
- <parameter name="f2"><paramtype><classname>function</classname><Signature, Allocator>&</paramtype></parameter>
+ <parameter name="f1"><paramtype><classname>function</classname><Signature>&</paramtype></parameter>
+ <parameter name="f2"><paramtype><classname>function</classname><Signature>&</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><Signature, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname><Signature>&</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><Signature, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname><Signature>&</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><Signature, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname><Signature>&</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname><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><classname>reference_wrapper</classname><Functor></paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>function</classname><Signature, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname><Signature>&</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><Signature1, Allocator1>&</paramtype></parameter>
- <parameter name="f2"><paramtype>const <classname>function</classname><Signature2, Allocator2>&</paramtype></parameter>
+ <parameter name="f1"><paramtype>const <classname>function</classname><Signature1>&</paramtype></parameter>
+ <parameter name="f2"><paramtype>const <classname>function</classname><Signature2>&</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><Signature, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname><Signature>&</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><Signature, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname><Signature>&</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><Signature, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname><Signature>&</paramtype></parameter>
<parameter name="g"><paramtype><classname>reference_wrapper</classname><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><classname>reference_wrapper</classname><Functor></paramtype></parameter>
- <parameter name="f"><paramtype>const <classname>function</classname><Signature, Allocator>&</paramtype></parameter>
+ <parameter name="f"><paramtype>const <classname>function</classname><Signature>&</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><Signature1, Allocator1>&</paramtype></parameter>
- <parameter name="f2"><paramtype>const <classname>function</classname><Signature2, Allocator2>&</paramtype></parameter>
+ <parameter name="f1"><paramtype>const <classname>function</classname><Signature1>&</paramtype></parameter>
+ <parameter name="f2"><paramtype>const <classname>function</classname><Signature2>&</paramtype></parameter>
</signature>
<returns><simpara>True when <code>f</code> does not store an
Modified: branches/release/libs/function/test/allocator_test.cpp
==============================================================================
--- branches/release/libs/function/test/allocator_test.cpp (original)
+++ branches/release/libs/function/test/allocator_test.cpp 2008-07-14 14:32:29 EDT (Mon, 14 Jul 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