Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r58432 - sandbox/function/boost/function
From: dsaritz_at_[hidden]
Date: 2009-12-17 11:35:24


Author: psiha
Date: 2009-12-17 11:35:23 EST (Thu, 17 Dec 2009)
New Revision: 58432
URL: http://svn.boost.org/trac/boost/changeset/58432

Log:
First changes: this is unfortunatelly one huge commit as it consists of many many changes that were done locally/offline/without source control so the individual steps are lost.

The most important changes are as follows:
  - there was a lot of functionality in the function_template.hpp (in the main
boost::function<> template class) that was not related/specific to the
particular boost::function<> instantiation and could be extracted into the
non-template function_base base class (and was causing actual bloat as the
compiler/linker did not/could not merge it)...moved as much of such code as
possible into the base header/class
  - along with that 'binary code duplication' caused by template code bloat
there was also a certain amount of source code duplication (like same
descisions being made both at the "front side" and the "back side", or type
information managing implemented both in the 'shared' manager and again in each
type specific manager...)
  - there is now only a single invoker template (actually two, the void
returning version of the first one)
  - there is now only one vtable type/struct (the one in the base header)
  - the invoker pointer was moved into the base vtable and was placed at the
beginning of the vtable so that the vtable pointer would point to it directly
(to avoid the pointer offset calculation mentioned in the "[optional] layout"
thread)
  - the invoker pointer/signature was changed to be a member function of the
function_buffer so that the thiscall calling convention would be used.
According to this information http://en.wikipedia.org/wiki/X86_calling_conventions#thiscall this makes no
difference for gcc but does for MSVC (and x86) because now the pointer to the
function_buffer is passed in the ECX register making the stack look exactly (or
more closely, depending on the target) as it needs to be to invoke the target
in the invoker function providing for a more direct call of the target (with no
or less stack adjustment/additional pushing/poping)
  - the manager design was changed to allow easier splitting and extracting of
functionality (and in the end for both smaller and faster code): previous
manager design used a combination of one function pointer and
'message'/'op-code' passing and switching...this, among other things, caused
 separate manager code to be generated for every different type of object
assigned to the boost::function<> object because the same function was
'managing' both the (obiously different) type information and the
move/clone/destroy functionality (which is actually shared for a vast majority
of assigned types of objects)...this was changed so that the op-codes were
replaced with an enlarged vtable with separate pointers/functions for move,
clone, destroy and type information functionality...type information
functionality was also changed so that the "back side" only creates an object
containing all the relevant information and passes it to the "front side" that
can then use how and _if_ it needs it (this way the type comparison code for
the target() member function is only generated if it is actually used)
 - cv-qualifier information for objects stored as references is also no
longer saved in two run-time bools but is encoded in the type of the "back
side" (so function_buffer::type_t is now typed_functor, and no longer needs to
reside in the function_buffer and function_buffer::obj_ref_t is gone all
together)
  - added more managers (total of 5, previously there were 3) that work with as
little type information as possible (the purpose and implementation should be
obvious from the source and acompanying comments)
  - the vtable static initialization was moved outside the vtable_for_functor()
function to ensure that static initialization was actually always used (with
increased numer of function pointers/size of the vtable MSVC would start using
lazy initialization...like in a 'normal' "Meyers' singleton")
  - the "has_trivial_copy_and_destroy" optimization and the encoding of that
information into the vtable pointer was removed because in practice it was
actually a pessimization (atleast/especially with the new design). If it
somehow turns out usefull at some later time it can now be more easily
implemented (e.g. with a larger vtable, the trivial functionality could simply
use null pointers...)...
  - assignment functionality was moved from the (no longer present)
boost::function<> instantiation-specific vtable struct (BOOST_FUNCTION_VTABLE)
into the appropriate functor manager classes in the base header
  - assignment functionality was also heavily optimized (although there is
still room for improvement)...until now the default 'safe' approach of
<copy-constructing a temporary and calling swap> was always used (which
resulted in hundreds if not a few thousands of asm instructions getting
executed, and was part of the template so it caused bloat)...now this is
done only for function objects that have nontrivial copy-constructors
and/or do not fit in the function_buffer (and is not part of the
template)...for the often case of simple binds and function pointers
assignment (and construction) now results in a call to the nothrow, and most
often trivial, destroy function and a couple of movs...
  - empty-invocation handling was changed to no longer place an "if (empty)
throw" section in the operator() (of the template class, thus pretty much
adding to bloat) but to use (assign to itself an) "EmptyHandler" function
object when in the empty state (that then gets invoked and does 'its
thing')...(this also removed the need for the msvc 6.0 workaround for the
in/out of class definition of the operator() function - as it is now only a
thin wrapper it can, actually should, be safely inlined)...
  - added BOOST_NO_TYPEID support that disables the type information
functionality
  - explicit exception handling was replaced with guard objects
  - const's were added, mutable's removed and pointers converted to references
    where ever possible
  - the generic has_empty_target() function was fixed for MSVC to always use
the ( void const * ) overload because MSVC does not inline vararg functions so
it was always generating calls to a function that only returns false (so it was
unable to remove code that does not execute for the false case)...
  - an additional template parameter was added to the main boost::function<>
template class called PolicyList (a list to cut down on the number of
parameters) that is expected to be a boost::mpl::map-like container of
policies. currently two policies exist:
  - - how to handle invocation of empty function objects (three default
handlers are provided: throw_on_empty, assert_on_empty and nop_on_empty)
  - - whether the function<> instantiation should 'report'/mark its operator()
      as nothrow and accept only nothrow targets (for supported compilers). For detail on the throw/nothrow implementation check the relevant boost.devel discusion (links are in the readme file).
Text files modified:
   sandbox/function/boost/function/function_base.hpp | 1462 ++++++++++++++++++++++++++++++---------
   sandbox/function/boost/function/function_fwd.hpp | 39
   sandbox/function/boost/function/function_template.hpp | 1195 ++++++++++----------------------
   3 files changed, 1543 insertions(+), 1153 deletions(-)

Modified: sandbox/function/boost/function/function_base.hpp
==============================================================================
--- sandbox/function/boost/function/function_base.hpp (original)
+++ sandbox/function/boost/function/function_base.hpp 2009-12-17 11:35:23 EST (Thu, 17 Dec 2009)
@@ -12,21 +12,43 @@
 #define BOOST_FUNCTION_BASE_HEADER
 
 #include <stdexcept>
+#include <stddef.h>
 #include <string>
 #include <memory>
 #include <new>
-#include <typeinfo>
+#ifndef BOOST_NO_TYPEID
+ #include <typeinfo>
+#endif // BOOST_NO_TYPEID
 #include <boost/config.hpp>
 #include <boost/assert.hpp>
 #include <boost/integer.hpp>
+
+#include <boost/aligned_storage.hpp>
+#include <boost/concept_check.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/type_traits/add_const.hpp>
+#include <boost/type_traits/add_reference.hpp>
+#include <boost/type_traits/has_nothrow_copy.hpp>
 #include <boost/type_traits/has_trivial_copy.hpp>
 #include <boost/type_traits/has_trivial_destructor.hpp>
+#include <boost/type_traits/is_base_of.hpp>
+#include <boost/type_traits/is_class.hpp>
 #include <boost/type_traits/is_const.hpp>
+#include <boost/type_traits/is_function.hpp>
+#include <boost/type_traits/is_fundamental.hpp>
 #include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_object.hpp>
+#include <boost/type_traits/is_stateless.hpp>
 #include <boost/type_traits/is_volatile.hpp>
 #include <boost/type_traits/composite_traits.hpp>
 #include <boost/type_traits/ice.hpp>
+#include <boost/type_traits/remove_const.hpp>
+#include <boost/type_traits/remove_pointer.hpp>
 #include <boost/ref.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/identity.hpp>
 #include <boost/mpl/if.hpp>
 #include <boost/detail/workaround.hpp>
 #include <boost/type_traits/alignment_of.hpp>
@@ -40,12 +62,16 @@
 
 #if defined(BOOST_MSVC)
 # pragma warning( push )
-# pragma warning( disable : 4793 ) // complaint about native code generation
 # pragma warning( disable : 4127 ) // "conditional expression is constant"
+# pragma warning( disable : 4510 ) // "default constructor could not be generated" (boost::detail::function::vtable)
+# pragma warning( disable : 4512 ) // "assignment operator could not be generated" (boost::detail::function::vtable)
+# pragma warning( disable : 4610 ) // "class can never be instantiated - user defined constructor required" (boost::detail::function::vtable)
+# pragma warning( disable : 4793 ) // complaint about native code generation
 #endif
 
+#ifndef BOOST_NO_TYPEID
 // Define BOOST_FUNCTION_STD_NS to the namespace that contains type_info.
-#ifdef BOOST_NO_STD_TYPEINFO
+#if defined( BOOST_NO_STD_TYPEINFO ) || ( defined( BOOST_MSVC ) && !_HAS_EXCEPTIONS )
 // Embedded VC++ does not have type_info in namespace std
 # define BOOST_FUNCTION_STD_NS
 #else
@@ -63,6 +89,7 @@
 # else
 # define BOOST_FUNCTION_COMPARE_TYPE_ID(X,Y) ((X)==(Y))
 #endif
+#endif // BOOST_NO_TYPEID
 
 #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 && !defined(BOOST_STRICT_CONFIG)
 # define BOOST_FUNCTION_TARGET_FIX(x) x
@@ -87,7 +114,72 @@
 namespace boost {
   namespace detail {
     namespace function {
- class X;
+
+ #ifndef BOOST_NO_TYPEID
+ // For transferring stored function object type information back to the
+ // interface side.
+ class typed_functor : noncopyable
+ {
+ public:
+ template <typename Functor>
+ typed_functor( Functor & functor )
+ :
+ pFunctor ( addressof( functor ) ),
+ type_id ( typeid( Functor ) ),
+ const_qualified ( is_const <Functor>::value ),
+ volatile_qualified( is_volatile<Functor>::value )
+ {
+ assert( pFunctor );
+ }
+
+ BOOST_FUNCTION_STD_NS::type_info const & functor_type_info() const { return type_id; }
+
+ template <typename Functor>
+ Functor * target()
+ {
+ // GCC 2.95.3 gets the CV qualifiers wrong here, so we
+ // can't do the static_cast that we should do.
+ return static_cast<Functor *>
+ (
+ get_functor_if_types_match
+ (
+ typeid( Functor ),
+ is_const <Functor>::value,
+ is_volatile<Functor>::value
+ )
+ );
+ }
+
+ private:
+ void * get_functor_if_types_match
+ (
+ BOOST_FUNCTION_STD_NS::type_info const & other,
+ bool const other_const_qualified,
+ bool const other_volatile_qualified
+ )
+ {
+ // Check whether we have the same type. We can add
+ // cv-qualifiers, but we can't take them away.
+ bool const types_match
+ (
+ BOOST_FUNCTION_COMPARE_TYPE_ID( type_id, other )
+ &&
+ ( !const_qualified || other_const_qualified )
+ &&
+ ( !volatile_qualified || other_volatile_qualified )
+ );
+ return types_match ? const_cast<void *>( pFunctor ) : 0;
+ }
+
+ private:
+ void const * const pFunctor;
+ BOOST_FUNCTION_STD_NS::type_info const & type_id;
+ // Whether the type is const-qualified.
+ bool const const_qualified;
+ // Whether the type is volatile-qualified.
+ bool const volatile_qualified;
+ };
+ #endif // BOOST_NO_TYPEID
 
       /**
        * A buffer used to store small function objects in
@@ -95,46 +187,73 @@
        * object pointers, and a structure that resembles a bound
        * member function pointer.
        */
+ #ifdef BOOST_MSVC
+ // http://msdn.microsoft.com/en-us/library/5ft82fed(VS.80).aspx (ad unions)
+ #define RESTRICT __restrict
+ #else
+ #define RESTRICT
+ #endif
       union function_buffer
       {
         // For pointers to function objects
- mutable void* obj_ptr;
+ void * RESTRICT obj_ptr;
 
- // For pointers to std::type_info objects
- struct type_t {
- // (get_functor_type_tag, check_functor_type_tag).
- const BOOST_FUNCTION_STD_NS::type_info* type;
-
- // Whether the type is const-qualified.
- bool const_qualified;
- // Whether the type is volatile-qualified.
- bool volatile_qualified;
- } type;
+ // For 'trivial' function objects (that can be managed without type
+ // information) that must be allocated on the heap (we must only save
+ // the object's size information for the clone operation).
+ struct trivial_heap_obj_t
+ {
+ void * ptr;
+ std::size_t size; // in number of allocation atoms
+ } trivial_heap_obj;
 
         // For function pointers of all kinds
- mutable void (*func_ptr)();
+ void (* RESTRICT func_ptr)();
 
         // For bound member pointers
         struct bound_memfunc_ptr_t {
+ class X;
           void (X::*memfunc_ptr)(int);
           void* obj_ptr;
         } bound_memfunc_ptr;
 
- // For references to function objects. We explicitly keep
- // track of the cv-qualifiers on the object referenced.
- struct obj_ref_t {
- mutable void* obj_ptr;
- bool is_const_qualified;
- bool is_volatile_qualified;
- } obj_ref;
-
         // To relax aliasing constraints
- mutable char data;
+ char data;
+ };
+ #undef RESTRICT
+
+ // A simple wrapper to allow deriving and a thiscall invoker.
+ struct function_buffer_holder { function_buffer buffer; };
+
+ // Check that all function_buffer "access points" are actually at the same
+ // address/offset.
+ BOOST_STATIC_ASSERT( offsetof( function_buffer, obj_ptr ) == offsetof( function_buffer, func_ptr ) );
+ BOOST_STATIC_ASSERT( offsetof( function_buffer, bound_memfunc_ptr ) == offsetof( function_buffer, func_ptr ) );
+ BOOST_STATIC_ASSERT( offsetof( function_buffer::bound_memfunc_ptr_t, memfunc_ptr ) == 0 );
+
+ template
+ <
+ typename throw_test_signature,
+ throw_test_signature * no_throw_test,
+ throw_test_signature * throw_test
+ >
+ struct is_nothrow_helper
+ {
+ static bool const is_nothrow;
       };
 
+ // is_nothrow_helper static member initialization
+ template <typename throw_test_signature, throw_test_signature * no_throw_test, throw_test_signature * throw_test>
+ bool const is_nothrow_helper
+ <
+ throw_test_signature,
+ no_throw_test,
+ throw_test
+ >::is_nothrow = ( no_throw_test == throw_test );
+
       /**
        * The unusable class is a placeholder for unused function arguments
- * It is also completely unusable except that it constructable from
+ * It is also completely unusable except that it constructible from
        * anything. This helps compilers without partial specialization to
        * handle Boost.Function objects returning void.
        */
@@ -148,22 +267,8 @@
        * void returns or partial specialization by silently changing the return
        * type to "unusable".
        */
- template<typename T> struct function_return_type { typedef T type; };
-
- template<>
- struct function_return_type<void>
- {
- typedef unusable type;
- };
-
- // The operation type to perform on the given functor/function pointer
- enum functor_manager_operation_type {
- clone_functor_tag,
- move_functor_tag,
- destroy_functor_tag,
- check_functor_type_tag,
- get_functor_type_tag
- };
+ template<typename T> struct function_return_type { typedef T type; };
+ template<> struct function_return_type<void> { typedef unusable type; };
 
       // Tags used to decide between different types of functions
       struct function_ptr_tag {};
@@ -171,10 +276,30 @@
       struct member_ptr_tag {};
       struct function_obj_ref_tag {};
 
+ // When functions and function pointers are decorated with exception
+ // specifications MSVC mangles their type (almost) beyond recognition.
+ // Even MSVC supplied type traits is_pointer, is_member_pointer and
+ // is_function no longer recognize them. This tester is a workaround that
+ // seems to work well enough for now.
+ template <typename T>
+ struct is_msvc_exception_specified_function_pointer
+ :
+ public mpl::bool_
+ <
+ #ifdef BOOST_MSVC
+ !is_class <T>::value &&
+ !is_fundamental<T>::value &&
+ ( sizeof( T ) == sizeof( void (*) (void) ) )
+ #else
+ false
+ #endif
+ >
+ {};
+
       template<typename F>
       class get_function_tag
       {
- typedef typename mpl::if_c<(is_pointer<F>::value),
+ typedef typename mpl::if_c<(is_pointer<F>::value || is_msvc_exception_specified_function_pointer<F>::value),
                                    function_ptr_tag,
                                    function_obj_tag>::type ptr_or_obj_tag;
 
@@ -190,251 +315,394 @@
         typedef or_ref_tag type;
       };
 
- // The trivial manager does nothing but return the same pointer (if we
- // are cloning) or return the null pointer (if we are deleting).
- template<typename F>
- struct reference_manager
+/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
+ template <typename F,typename A>
+ struct functor_wrapper: public F, public A
       {
- static inline void
- manage(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
+ functor_wrapper( F f, A a ):
+ F(f),
+ A(a)
         {
- switch (op) {
- case clone_functor_tag:
- out_buffer.obj_ref.obj_ptr = in_buffer.obj_ref.obj_ptr;
- return;
-
- case move_functor_tag:
- out_buffer.obj_ref.obj_ptr = in_buffer.obj_ref.obj_ptr;
- in_buffer.obj_ref.obj_ptr = 0;
- return;
+ }
+
+ functor_wrapper(const functor_wrapper& f) :
+ F(static_cast<const F&>(f)),
+ A(static_cast<const A&>(f))
+ {
+ }
+ };
+*/
 
- case destroy_functor_tag:
- out_buffer.obj_ref.obj_ptr = 0;
- return;
+ template<typename Functor>
+ struct functor_traits
+ {
+ BOOST_STATIC_CONSTANT
+ (bool,
+ allowsPODOptimization =
+ is_msvc_exception_specified_function_pointer<Functor>::value ||
+ (
+ has_trivial_copy_constructor<Functor>::value &&
+ has_trivial_destructor <Functor>::value
+ ));
+
+ BOOST_STATIC_CONSTANT
+ (bool,
+ allowsSmallObjectOptimization =
+ is_msvc_exception_specified_function_pointer<Functor>::value ||
+ (
+ ( sizeof( Functor ) <= sizeof( function_buffer ) ) &&
+ ( alignment_of<function_buffer>::value % alignment_of<Functor>::value == 0 ) &&
+ allowsPODOptimization
+ ));
+
+ BOOST_STATIC_CONSTANT
+ (bool,
+ allowsPtrObjectOptimization =
+ is_msvc_exception_specified_function_pointer<Functor>::value ||
+ (
+ ( sizeof( Functor ) <= sizeof( void * ) &&
+ ( alignment_of<void *>::value % alignment_of<Functor>::value == 0 ) &&
+ allowsPODOptimization)
+ ));
+
+ BOOST_STATIC_CONSTANT
+ (bool,
+ hasDefaultAlignement =
+ alignment_of<Functor>::value == alignment_of<manager_trivial_heap::storage_atom>::value);
+ };
 
- case check_functor_type_tag:
- {
- const BOOST_FUNCTION_STD_NS::type_info& check_type
- = *out_buffer.type.type;
 
- // Check whether we have the same type. We can add
- // cv-qualifiers, but we can't take them away.
- if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F))
- && (!in_buffer.obj_ref.is_const_qualified
- || out_buffer.type.const_qualified)
- && (!in_buffer.obj_ref.is_volatile_qualified
- || out_buffer.type.volatile_qualified))
- out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
- else
- out_buffer.obj_ptr = 0;
- }
- return;
+ /// A helper class that can construct a typed_functor object from a
+ /// function_buffer instance for given template parameters.
+ template
+ <
+ typename ActualFunctor,
+ typename StoredFunctor,
+ class FunctorManager
+ >
+ class functor_type_info
+ {
+ #ifndef BOOST_NO_TYPEID
+ private:
+ template <bool is_ref_wrapper, bool is_member_pointer>
+ static ActualFunctor * actual_functor_ptr( StoredFunctor * storedFunctor );
 
- case get_functor_type_tag:
- out_buffer.type.type = &typeid(F);
- out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
- out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
- return;
+ template <>
+ static ActualFunctor * actual_functor_ptr<true, false>( StoredFunctor * pStoredFunctor )
+ {
+ // needed when StoredFunctor is a static reference
+ ignore_unused_variable_warning( pStoredFunctor );
+ return pStoredFunctor->get_pointer();
           }
- }
+ template <>
+ static ActualFunctor * actual_functor_ptr<false, true>( StoredFunctor * pStoredFunctor )
+ {
+ BOOST_STATIC_ASSERT( sizeof( StoredFunctor ) == sizeof( ActualFunctor ) );
+ return static_cast<ActualFunctor *>( static_cast<void *>( pStoredFunctor ) );
+ }
+ template <>
+ static ActualFunctor * actual_functor_ptr<false, false>( StoredFunctor * pStoredFunctor )
+ {
+ BOOST_STATIC_ASSERT
+ ((
+ ( is_same<remove_cv<ActualFunctor>::type, StoredFunctor>::value ) ||
+ (
+ is_msvc_exception_specified_function_pointer<ActualFunctor>::value &&
+ is_msvc_exception_specified_function_pointer<StoredFunctor>::value &&
+ sizeof( ActualFunctor ) == sizeof( StoredFunctor )
+ )
+ ));
+ return pStoredFunctor;
+ }
+ public:
+ static typed_functor get_typed_functor( function_buffer const & buffer )
+ {
+ StoredFunctor * const pStoredFunctor( FunctorManager::functor_ptr( const_cast<function_buffer &>( buffer ) ) );
+ ActualFunctor * const pActualFunctor( actual_functor_ptr<is_reference_wrapper<StoredFunctor>::value, is_member_pointer<ActualFunctor>::value>( pStoredFunctor ) );
+ return typed_functor( *pActualFunctor );
+ }
+ #endif // BOOST_NO_TYPEID
       };
 
- /**
- * Determine if boost::function can use the small-object
- * optimization with the function object type F.
- */
- template<typename F>
- struct function_allows_small_object_optimization
+ // A helper wrapper class that adds type information functionality (e.g.
+ // for non typed/trivial managers).
+ template
+ <
+ class FunctorManager,
+ typename ActualFunctor,
+ typename StoredFunctor = FunctorManager::Functor
+ >
+ struct typed_manager
+ :
+ public FunctorManager,
+ public functor_type_info<ActualFunctor, StoredFunctor, typed_manager<FunctorManager, ActualFunctor, StoredFunctor>>
       {
- BOOST_STATIC_CONSTANT
- (bool,
- value = ((sizeof(F) <= sizeof(function_buffer) &&
- (alignment_of<function_buffer>::value
- % alignment_of<F>::value == 0))));
+ typedef StoredFunctor Functor;
+ static StoredFunctor * functor_ptr( function_buffer & buffer ) { return (StoredFunctor *)FunctorManager::functor_ptr( buffer ); }
       };
 
- template <typename F,typename A>
- struct functor_wrapper: public F, public A
+ /// Manager for trivial objects that fit into sizeof( void * ).
+ struct manager_ptr
       {
- functor_wrapper( F f, A a ):
- F(f),
- A(a)
- {
- }
-
- functor_wrapper(const functor_wrapper& f) :
- F(static_cast<const F&>(f)),
- A(static_cast<const A&>(f))
- {
- }
+ public:
+ static void * * functor_ptr( function_buffer & buffer ) { return &buffer.obj_ptr; }
+ static void const * const * functor_ptr( function_buffer const & buffer ) { return functor_ptr( const_cast<function_buffer &>( buffer ) ); }
+
+ template <typename Functor>
+ static void assign( Functor const & functor, function_buffer & out_buffer )
+ {
+ BOOST_STATIC_ASSERT( functor_traits<Functor>::allowsPtrObjectOptimization );
+ new ( functor_ptr( out_buffer ) ) Functor( functor );
+ }
+
+ static void clone( const function_buffer& in_buffer, function_buffer& out_buffer )
+ {
+ return assign( *functor_ptr( in_buffer ), out_buffer );
+ }
+
+ static void move( function_buffer & in_buffer, function_buffer& out_buffer )
+ {
+ clone( in_buffer, out_buffer );
+ destroy( in_buffer );
+ }
+
+ static void destroy( function_buffer& buffer )
+ {
+ //...probably unnecessary
+ *functor_ptr( buffer ) = 0;
+ }
       };
 
- /**
- * The functor_manager class contains a static function "manage" which
- * can clone or destroy the given function/function object pointer.
- */
- template<typename Functor>
- struct functor_manager_common
+ /// Manager for trivial objects that can live in a function_buffer.
+ struct manager_trivial_small
       {
- typedef Functor functor_type;
+ public:
+ static void * functor_ptr( function_buffer & buffer ) { return &buffer; }
 
- // Function pointers
- static inline void
- manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
- {
- if (op == clone_functor_tag)
- out_buffer.func_ptr = in_buffer.func_ptr;
- else if (op == move_functor_tag) {
- out_buffer.func_ptr = in_buffer.func_ptr;
- in_buffer.func_ptr = 0;
- } else if (op == destroy_functor_tag)
- out_buffer.func_ptr = 0;
- else if (op == check_functor_type_tag) {
- const BOOST_FUNCTION_STD_NS::type_info& check_type
- = *out_buffer.type.type;
- if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
- out_buffer.obj_ptr = &in_buffer.func_ptr;
- else
- out_buffer.obj_ptr = 0;
- } else /* op == get_functor_type_tag */ {
- out_buffer.type.type = &typeid(Functor);
- out_buffer.type.const_qualified = false;
- out_buffer.type.volatile_qualified = false;
+ template <typename Functor>
+ static void assign( Functor const & functor, function_buffer & out_buffer )
+ {
+ BOOST_STATIC_ASSERT
+ (
+ functor_traits<Functor>::allowsPODOptimization &&
+ functor_traits<Functor>::allowsSmallObjectOptimization
+ );
+ new ( functor_ptr( out_buffer ) ) Functor( functor );
           }
- }
 
- // Function objects that fit in the small-object buffer.
- static inline void
- manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
- {
- if (op == clone_functor_tag || op == move_functor_tag) {
- const functor_type* in_functor =
- reinterpret_cast<const functor_type*>(&in_buffer.data);
- new ((void*)&out_buffer.data) functor_type(*in_functor);
-
- if (op == move_functor_tag) {
- reinterpret_cast<functor_type*>(&in_buffer.data)->~Functor();
- }
- } else if (op == destroy_functor_tag) {
- // Some compilers (Borland, vc6, ...) are unhappy with ~functor_type.
- reinterpret_cast<functor_type*>(&out_buffer.data)->~Functor();
- } else if (op == check_functor_type_tag) {
- const BOOST_FUNCTION_STD_NS::type_info& check_type
- = *out_buffer.type.type;
- if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
- out_buffer.obj_ptr = &in_buffer.data;
- else
- out_buffer.obj_ptr = 0;
- } else /* op == get_functor_type_tag */ {
- out_buffer.type.type = &typeid(Functor);
- out_buffer.type.const_qualified = false;
- out_buffer.type.volatile_qualified = false;
+ static void clone( function_buffer const & in_buffer, function_buffer & out_buffer )
+ {
+ return assign( in_buffer, out_buffer );
+ }
+
+ static void move( function_buffer & in_buffer, function_buffer & out_buffer )
+ {
+ clone( in_buffer, out_buffer );
+ destroy( in_buffer );
+ }
+
+ static void destroy( function_buffer & buffer )
+ {
+ //...probably unnecessary
+ std::memset( &buffer, 0, sizeof( buffer ) );
           }
- }
       };
 
- template<typename Functor>
- struct functor_manager
+ /// Manager for trivial objects that cannot live/fit in a function_buffer.
+ struct manager_trivial_heap
       {
- private:
- typedef Functor functor_type;
+ public:
+ typedef boost::aligned_storage<sizeof( void * ) * 2, sizeof( void * ) * 2>::type storage_atom;
 
- // 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);
- }
+ public:
+ static void * & functor_ptr( function_buffer & buffer ) { return buffer.trivial_heap_obj.ptr; }
+ static void * functor_ptr( function_buffer const & buffer ) { return functor_ptr( const_cast<function_buffer &>( buffer ) ); }
 
- // Function objects that fit in the small-object buffer.
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, mpl::true_)
- {
- functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
- }
-
- // Function objects that require heap allocation
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, mpl::false_)
- {
- if (op == clone_functor_tag) {
- // Clone the functor
- // GCC 2.95.3 gets the CV qualifiers wrong here, so we
- // can't do the static_cast that we should do.
- const functor_type* f =
- (const functor_type*)(in_buffer.obj_ptr);
- functor_type* new_f = new functor_type(*f);
- out_buffer.obj_ptr = new_f;
- } else if (op == move_functor_tag) {
- out_buffer.obj_ptr = in_buffer.obj_ptr;
- in_buffer.obj_ptr = 0;
- } else if (op == destroy_functor_tag) {
- /* Cast from the void pointer to the functor pointer type */
- functor_type* f =
- static_cast<functor_type*>(out_buffer.obj_ptr);
- delete f;
- out_buffer.obj_ptr = 0;
- } else if (op == check_functor_type_tag) {
- const BOOST_FUNCTION_STD_NS::type_info& check_type
- = *out_buffer.type.type;
- if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(Functor)))
- out_buffer.obj_ptr = in_buffer.obj_ptr;
- else
- out_buffer.obj_ptr = 0;
- } else /* op == get_functor_type_tag */ {
- out_buffer.type.type = &typeid(Functor);
- out_buffer.type.const_qualified = false;
- out_buffer.type.volatile_qualified = false;
+ template <typename Functor>
+ static void assign( Functor const & functor, function_buffer & out_buffer )
+ {
+ BOOST_STATIC_ASSERT
+ (
+ functor_traits<Functor>::allowsPODOptimization &&
+ functor_traits<Functor>::hasDefaultAlignement
+ );
+ function_buffer in_buffer;
+ in_buffer.trivial_heap_obj.ptr = const_cast<Functor *>( &functor );
+ in_buffer.trivial_heap_obj.size = ( sizeof( Functor ) / sizeof( storage_atom ) )
+ +
+ ( ( sizeof( Functor ) % sizeof( storage_atom ) ) ? 1 : 0 );
+ return clone( in_buffer, out_buffer );
           }
- }
 
- // 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)>());
- }
+ static void clone( function_buffer const & in_buffer, function_buffer & out_buffer )
+ {
+ std::size_t const storage_array_size( in_buffer.trivial_heap_obj.size );
+ out_buffer.trivial_heap_obj.ptr = new storage_atom[ storage_array_size ];
+ out_buffer.trivial_heap_obj.size = storage_array_size;
+ std::memcpy( functor_ptr( out_buffer ), functor_ptr( in_buffer ), storage_array_size );
+ }
 
- // For member pointers, we use the small-object optimization buffer.
- static inline void
- manager(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op, member_ptr_tag)
- {
- manager(in_buffer, out_buffer, op, mpl::true_());
- }
+ static void move( function_buffer & in_buffer, function_buffer & out_buffer )
+ {
+ out_buffer.trivial_heap_obj = in_buffer.trivial_heap_obj;
+ //...probably unnecessary
+ in_buffer.trivial_heap_obj.ptr = 0;
+ }
 
+ static void destroy( function_buffer & buffer )
+ {
+ delete [] functor_ptr( buffer );
+ //...probably unnecessary
+ functor_ptr( buffer ) = 0;
+ }
+ };
+
+ /// Manager for non-trivial objects that can live in a function_buffer.
+ template <typename Functor>
+ struct manager_small
+ {
       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.type.type = &typeid(functor_type);
- out_buffer.type.const_qualified = false;
- out_buffer.type.volatile_qualified = false;
- return;
+ typedef Functor Functor;
 
- default:
- manager(in_buffer, out_buffer, op, tag_type());
- return;
+ static Functor * functor_ptr( function_buffer & buffer ) { return static_cast<Functor *>( manager_trivial_small::functor_ptr( buffer ) ); }
+ static Functor const * functor_ptr( function_buffer const & buffer ) { return functor_ptr( const_cast<function_buffer &>( buffer ) ); }
+
+ static void assign( Functor const & functor, function_buffer & out_buffer )
+ {
+ new ( functor_ptr( out_buffer ) ) Functor( functor );
+ }
+
+ static void clone( function_buffer const & in_buffer, function_buffer & out_buffer )
+ {
+ Functor const & in_functor( *functor_ptr( in_buffer ) );
+ return assign( in_functor, out_buffer );
+ }
+
+ static void move( function_buffer & in_buffer, function_buffer & out_buffer )
+ {
+ // ...use swap here?
+ clone( in_buffer, out_buffer );
+ destroy( in_buffer );
+ }
+
+ static void destroy( function_buffer & buffer )
+ {
+ functor_ptr( buffer )->~Functor();
           }
- }
       };
 
+ /// Fully generic manager for non-trivial objects that cannot live/fit in
+ /// a function_buffer.
+ template <typename Functor>
+ struct manager_generic
+ {
+ public:
+ typedef Functor Functor;
+
+ static Functor * & functor_ptr( function_buffer & buffer )
+ {
+ // 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.
+ // ...recheck the above comment after all these changes...
+ return (Functor * &)manager_trivial_heap::functor_ptr( buffer );
+ }
+
+ static Functor * functor_ptr( function_buffer const & buffer )
+ {
+ return functor_ptr( const_cast<function_buffer &>( buffer ) );
+ }
+
+ static void assign( Functor const & functor, function_buffer & out_buffer )
+ {
+ functor_ptr( out_buffer ) = new Functor( functor );
+ }
+
+ static void clone( const function_buffer& in_buffer, function_buffer& out_buffer )
+ {
+ Functor const & in_functor( *functor_ptr( in_buffer ) );
+ return assign( in_functor, out_buffer );
+ }
+
+ static void move( function_buffer & in_buffer, function_buffer& out_buffer )
+ {
+ manager_trivial_heap::move( in_buffer, out_buffer );
+ }
+
+ static void destroy( function_buffer& buffer )
+ {
+ checked_delete( functor_ptr( buffer ) );
+ //...probably unnecessary
+ functor_ptr( buffer ) = 0;
+ }
+ };
+
+ /// Helper metafunction for retrieving an appropriate functor manager.
+ template
+ <
+ typename Functor,
+ bool POD,
+ bool smallObj,
+ bool ptrSmall,
+ bool defaultAligned
+ >
+ struct functor_manager
+ {
+ typedef manager_generic<Functor> type;
+ };
+
+ template<typename Functor>
+ struct functor_manager<Functor, true, false, false, true>
+ {
+ typedef manager_trivial_heap type;
+ };
+
+ template<typename Functor, bool defaultAligned>
+ struct functor_manager<Functor, true, true, false, defaultAligned>
+ {
+ typedef manager_trivial_small type;
+ };
+
+ template<typename Functor, bool smallObj, bool defaultAligned>
+ struct functor_manager<Functor, true, smallObj, true, defaultAligned>
+ {
+ typedef manager_ptr type;
+ };
+
+ template<typename Functor, bool ptrSmall, bool defaultAligned>
+ struct functor_manager<Functor, false, true, ptrSmall, defaultAligned>
+ {
+ typedef manager_small<Functor> type;
+ };
+
+ /// Metafunction for retrieving an appropriate functor manager with
+ /// minimal type information.
+ template<typename StoredFunctor>
+ struct get_functor_manager
+ {
+ typedef typename functor_manager
+ <
+ StoredFunctor,
+ functor_traits<StoredFunctor>::allowsPODOptimization,
+ functor_traits<StoredFunctor>::allowsSmallObjectOptimization,
+ functor_traits<StoredFunctor>::allowsPtrObjectOptimization,
+ functor_traits<StoredFunctor>::hasDefaultAlignement
+ >::type type;
+ };
+
+ /// Metafunction for retrieving an appropriate fully typed functor manager.
+ template<typename ActualFunctor, typename StoredFunctor>
+ struct get_typed_functor_manager
+ {
+ typedef typed_manager
+ <
+ typename get_functor_manager<StoredFunctor>::type,
+ ActualFunctor,
+ StoredFunctor
+ > type;
+ };
+
+/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
       template<typename Functor, typename Allocator>
       struct functor_manager_a
       {
@@ -446,7 +714,7 @@
         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);
+ manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
         }
 
         // Function objects that fit in the small-object buffer.
@@ -454,7 +722,7 @@
         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);
+ manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
         }
         
         // Function objects that require heap allocation
@@ -484,7 +752,7 @@
             out_buffer.obj_ptr = in_buffer.obj_ptr;
             in_buffer.obj_ptr = 0;
           } else if (op == destroy_functor_tag) {
- /* Cast from the void pointer to the functor_wrapper_type */
+ // 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));
@@ -498,7 +766,7 @@
               out_buffer.obj_ptr = in_buffer.obj_ptr;
             else
               out_buffer.obj_ptr = 0;
- } else /* op == get_functor_type_tag */ {
+ } else { // op == get_functor_type_tag
             out_buffer.type.type = &typeid(Functor);
             out_buffer.type.const_qualified = false;
             out_buffer.type.volatile_qualified = false;
@@ -517,8 +785,8 @@
         }
 
       public:
- /* Dispatch to an appropriate manager based on whether we have a
- function pointer or a function object pointer. */
+ // 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)
@@ -537,6 +805,7 @@
           }
         }
       };
+*/
 
       // A type that is only used for comparisons against zero
       struct useless_clear_type {};
@@ -600,15 +869,83 @@
         }
 #endif // BOOST_NO_SFINAE
 
- /**
- * Stores the "manager" portion of the vtable for a
- * boost::function object.
- */
- struct vtable_base
+ // The "generic typed/void-void invoker pointer is also stored here so
+ // that it can (more easily) be placed at the beginning of the vtable so
+ // that a vtable pointer would actually point directly to it (thus
+ // avoiding pointer offset calculation on invocation).
+ struct vtable
+ {
+ typedef void ( function_buffer_holder::* invoker_placeholder_type )( void );
+ template<typename TargetInvokerType>
+ TargetInvokerType const & invoker() const { return reinterpret_cast<TargetInvokerType const &>( void_invoker ); }
+
+ void clone ( function_buffer const & in_buffer, function_buffer & out_buffer ) const { do_clone( in_buffer, out_buffer ); }
+ void move ( function_buffer & in_buffer, function_buffer & out_buffer ) const { do_move ( in_buffer, out_buffer ); }
+ #ifdef BOOST_MSVC
+ __declspec( nothrow )
+ #endif
+ void destroy( function_buffer & buffer ) const { do_destroy( buffer ); }
+
+ // The possibly-decorated-invoker-wrapper is not used here because MSVC
+ // (9.0 SP1) needlessly copy-constructs the returned typed_functor
+ // object even if the thin invoker-wrapper is __forceinlined.
+ //typed_functor get_typed_functor( function_buffer const & buffer ) const { return do_get_typed_functor( buffer ); }
+
+ public: // "Private but not private" to enable aggregate-style initialization.
+ invoker_placeholder_type const void_invoker;
+
+ void (& do_clone )( function_buffer const & in_buffer, function_buffer & out_buffer );
+ void (& do_move )( function_buffer & in_buffer, function_buffer & out_buffer );
+ void (& do_destroy )( function_buffer & buffer );
+
+ #ifndef BOOST_NO_TYPEID
+ // Because of the MSVC issue described above we mark the
+ // get_typed_functor function as nothrow like this, explicitly (because
+ // MSVC does not properly support exception specifications this is not a
+ // pessimization...it is equivalent to __declspec( nothrow )).
+ typed_functor (& get_typed_functor )( function_buffer const & )
+ #ifdef BOOST_MSVC
+ throw()
+ #endif
+ ;
+ #endif // BOOST_NO_TYPEID
+
+
+/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
+ template<typename FunctionObj,typename Allocator>
+ void
+ assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const
+ {
+ 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 <class Invoker, class Manager>
+ struct vtable_holder { static vtable const stored_vtable; };
+
+ // Note: it is extremely important that this initialization use
+ // static initialization. Otherwise, we will have a race
+ // condition here in multi-threaded code. See
+ // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
+ template <class Invoker, class Manager>
+ vtable const vtable_holder<Invoker, Manager>::stored_vtable =
       {
- void (*manager)(const function_buffer& in_buffer,
- function_buffer& out_buffer,
- functor_manager_operation_type op);
+ reinterpret_cast<vtable::invoker_placeholder_type>( &Invoker::invoke ),
+ &Manager::clone,
+ &Manager::move,
+ &Manager::destroy
+ #ifndef BOOST_NO_TYPEID
+ ,&Manager::get_typed_functor
+ #endif // BOOST_NO_TYPEID
       };
     } // end namespace function
   } // end namespace detail
@@ -621,56 +958,100 @@
  */
 class function_base
 {
-public:
- function_base() : vtable(0) { }
+private: // Private helper guard classes.
+ // ...(definition) to be moved out of body
 
- /** Determine if the function is empty (i.e., has no target). */
- bool empty() const { return !vtable; }
+ // ...if the is_stateless<EmptyHandler> requirement sticks this will not need
+ // to be a template...
+ template <class EmptyHandler>
+ class cleaner : noncopyable
+ {
+ typedef detail::function::vtable vtable;
+ public:
+ cleaner
+ (
+ function_base & function,
+ vtable const & empty_handler_vtable
+ )
+ :
+ pFunction_ ( &function ),
+ empty_handler_vtable_( empty_handler_vtable )
+ {}
 
- /** Retrieve the type of the stored function object, or typeid(void)
- if this is empty. */
- const BOOST_FUNCTION_STD_NS::type_info& target_type() const
+ ~cleaner() { conditional_clear( pFunction_ != 0 ); }
+
+ void cancel() { assert( pFunction_ ); pFunction_ = 0; }
+
+ private:
+ void conditional_clear( bool const clear )
+ {
+ using namespace detail::function;
+ if ( clear )
+ {
+ assert( pFunction_ );
+ typedef functor_traits<EmptyHandler> empty_handler_traits;
+ typedef get_functor_manager<EmptyHandler>::type empty_handler_manager;
+ // remove completely or replace with a simple is_stateless<>?
+ BOOST_STATIC_ASSERT
+ (
+ empty_handler_traits::allowsPODOptimization &&
+ empty_handler_traits::allowsSmallObjectOptimization
+ );
+ empty_handler_manager::assign( EmptyHandler(), pFunction_->functor );
+ pFunction_->pVTable = &empty_handler_vtable_;
+ }
+ }
+
+ private:
+ function_base * pFunction_;
+ vtable const & empty_handler_vtable_;
+ };
+
+ class safe_mover_base;
+ template <class EmptyHandler>
+ class safe_mover;
+
+public:
+ function_base( detail::function::vtable const & vtable ) : pVTable( &vtable ) { }
+ ~function_base() { destroy(); }
+
+ template <class EmptyHandler>
+ void swap( function_base & other, detail::function::vtable const & empty_handler_vtable )
   {
- if (!vtable) return typeid(void);
+ if (&other == this)
+ return;
+
+ function_base tmp( empty_handler_vtable );
 
- detail::function::function_buffer type;
- get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
- return *type.type.type;
+ safe_mover<EmptyHandler> my_restorer ( *this, tmp );
+
+ safe_mover<EmptyHandler> other_restorer( other, *this );
+
+ safe_mover_base::move( tmp, other, empty_handler_vtable );
+
+ my_restorer.cancel();
+ other_restorer.cancel();
   }
 
- template<typename Functor>
- Functor* target()
- {
- if (!vtable) return 0;
+#ifndef BOOST_NO_TYPEID
 
- detail::function::function_buffer type_result;
- type_result.type.type = &typeid(Functor);
- type_result.type.const_qualified = is_const<Functor>::value;
- type_result.type.volatile_qualified = is_volatile<Functor>::value;
- get_vtable()->manager(functor, type_result,
- detail::function::check_functor_type_tag);
- return static_cast<Functor*>(type_result.obj_ptr);
- }
+ /// Retrieve the type of the stored function object.
+ const BOOST_FUNCTION_STD_NS::type_info& target_type() const
+ {
+ return get_vtable().get_typed_functor( this->functor ).functor_type_info();
+ }
 
- template<typename Functor>
-#if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300)
- const Functor* target( Functor * = 0 ) const
-#else
- const Functor* target() const
-#endif
- {
- if (!vtable) return 0;
+ template <typename Functor>
+ Functor * target()
+ {
+ return get_vtable().get_typed_functor( this->functor ).target<Functor>();
+ }
 
- detail::function::function_buffer type_result;
- type_result.type.type = &typeid(Functor);
- type_result.type.const_qualified = true;
- type_result.type.volatile_qualified = is_volatile<Functor>::value;
- get_vtable()->manager(functor, type_result,
- detail::function::check_functor_type_tag);
- // GCC 2.95.3 gets the CV qualifiers wrong here, so we
- // can't do the static_cast that we should do.
- return (const Functor*)(type_result.obj_ptr);
- }
+ template <typename Functor>
+ Functor const * target() const
+ {
+ return const_cast<function_base &>( *this ).target<Functor const>();
+ }
 
   template<typename F>
     bool contains(const F& f) const
@@ -710,51 +1091,316 @@
     }
 #endif
 
+#endif // BOOST_NO_TYPEID
+
 public: // should be protected, but GCC 2.95.3 will fail to allow access
- detail::function::vtable_base* get_vtable() const {
- return reinterpret_cast<detail::function::vtable_base*>(
- reinterpret_cast<std::size_t>(vtable) & ~(std::size_t)0x01);
+ detail::function::vtable const & get_vtable() const
+ {
+ assert( pVTable );
+ #ifdef BOOST_MSVC
+ __assume( pVTable );
+ #endif // BOOST_MSVC
+ return *pVTable;
+ }
+
+protected:
+ template <class EmptyHandler>
+ #ifdef BOOST_MSVC
+ __declspec( nothrow )
+ #endif
+ void clear( detail::function::vtable const & empty_handler_vtable )
+ {
+ // If we hold to the is_stateless<EmptyHandler> requirement a full assign
+ // is not necessary here but a simple
+ // this->pVTable = &empty_handler_vtable...
+ EmptyHandler const emptyHandler;
+ assign<false, EmptyHandler>( emptyHandler, empty_handler_vtable, empty_handler_vtable );
+ }
+
+private: // Assignment from another boost function helpers.
+ __declspec( noinline )
+ void assign_direct( function_base const & source )
+ {
+ source.pVTable->clone( source.functor, this->functor );
+ pVTable = source.pVTable;
+ }
+
+ template <class EmptyHandler>
+ __declspec( noinline )
+ void assign_guarded( function_base const & source, detail::function::vtable const & empty_handler_vtable )
+ {
+ this->destroy();
+ cleaner<EmptyHandler> guard( *this, empty_handler_vtable );
+ assign_direct( source );
+ guard.cancel();
+ }
+
+protected:
+ // Assignment from another boost function.
+ template<bool direct, typename EmptyHandler, typename FunctionObj>
+ typename enable_if<is_base_of<function_base, FunctionObj>>::type
+ assign
+ (
+ FunctionObj const & f,
+ detail::function::vtable const & functor_vtable,
+ detail::function::vtable const & empty_handler_vtable
+ )
+ {
+ assert( &functor_vtable == f.pVTable );
+ boost::ignore_unused_variable_warning( functor_vtable );
+ if ( direct )
+ {
+ assert( &static_cast<function_base const &>( f ) != this );
+ assert( this->pVTable == &empty_handler_vtable );
+ assign_direct( f );
+ }
+ else if( &static_cast<function_base const &>( f ) != this )
+ {
+ assign_guarded<EmptyHandler>( f, empty_handler_vtable );
+ }
   }
 
- bool has_trivial_copy_and_destroy() const {
- return reinterpret_cast<std::size_t>(vtable) & 0x01;
+ // General actual assignment.
+ template<bool direct, typename EmptyHandler, typename FunctionObj>
+ typename disable_if<is_base_of<function_base, FunctionObj>>::type
+ assign
+ (
+ FunctionObj const & f,
+ detail::function::vtable const & functor_vtable,
+ detail::function::vtable const & empty_handler_vtable
+ )
+ {
+ using namespace detail::function;
+
+ if ( has_empty_target( boost::addressof( f ) ) )
+ this->clear<EmptyHandler>( empty_handler_vtable );
+ else
+ if ( direct )
+ {
+ assert( this->pVTable == &empty_handler_vtable );
+ typedef get_functor_manager<FunctionObj>::type functor_manager;
+ functor_manager::assign( f, this->functor );
+ this->pVTable = &functor_vtable;
+ return;
+ }
+ else
+ {
+ // This can/should be rewritten because the small-object-optimization
+ // condition is too strict (requires a trivial destructor which is not
+ // needed for a no fail assignment).
+ bool const has_no_fail_assignement
+ (
+ functor_traits<FunctionObj>::allowsSmallObjectOptimization &&
+ (
+ has_nothrow_copy_constructor<FunctionObj>::value ||
+ has_trivial_copy_constructor<FunctionObj>::value ||
+ is_msvc_exception_specified_function_pointer<FunctionObj>::value
+ )
+ );
+
+ actual_assign<EmptyHandler>
+ (
+ f,
+ functor_vtable,
+ empty_handler_vtable,
+ mpl::bool_<has_no_fail_assignement>()
+ );
+ }
   }
 
- detail::function::vtable_base* vtable;
- mutable detail::function::function_buffer functor;
+ template<typename EmptyHandler, typename FunctionObj>
+ #ifdef BOOST_MSVC
+ __declspec( nothrow )
+ #endif
+ void actual_assign
+ (
+ FunctionObj const & f,
+ detail::function::vtable const & functor_vtable,
+ detail::function::vtable const & /*empty_handler_vtable*/,
+ mpl::true_ /*can use direct assign*/
+ )
+ {
+ typedef detail::function::get_functor_manager<FunctionObj>::type functor_manager;
+ this->destroy();
+ functor_manager::assign( f, this->functor );
+ this->pVTable = &functor_vtable;
+ }
+
+ template<typename EmptyHandler, typename FunctionObj>
+ void actual_assign
+ (
+ FunctionObj const & f,
+ detail::function::vtable const & functor_vtable,
+ detail::function::vtable const & empty_handler_vtable,
+ mpl::false_ /*must use safe assignment*/
+ )
+ {
+ // This most generic case needs to be reworked [currently uses redundant
+ // copying (generic one, through function pointers) and does not use all
+ // the type information it can...]...
+ typedef detail::function::get_functor_manager<FunctionObj>::type functor_manager;
+ function_base tmp( empty_handler_vtable );
+ functor_manager::assign( f, tmp.functor );
+ tmp.pVTable = &functor_vtable;
+ this->swap<EmptyHandler>( tmp, empty_handler_vtable );
+ }
+
+ struct dummy { void nonnull() {}; };
+ typedef void (dummy::*safe_bool)();
+
+private:
+ #ifdef BOOST_MSVC
+ // MSVC (9.0 SP1) inlines this even with /Oxs for (probably) no gain so we
+ // force it not to (anti-code-bloat).
+ __declspec( noinline nothrow )
+ #endif
+ void destroy() { get_vtable().destroy( this->functor ); }
+
+protected:
+ // Fix/properly encapsulate these members and use the function_buffer_holder.
+ detail::function::vtable const * pVTable;
+ mutable detail::function::function_buffer functor;
 };
 
-/**
- * The bad_function_call exception class is thrown when a boost::function
- * object is invoked
- */
+
+class function_base::safe_mover_base : noncopyable
+{
+protected:
+ typedef detail::function::vtable vtable;
+ typedef detail::function::function_buffer functor;
+
+protected:
+ safe_mover_base( function_base & functionToGuard, function_base & emptyFunctionToMoveTo )
+ :
+ pFunctionToRestoreTo ( &functionToGuard ),
+ emptyFunctionToMoveTo_( emptyFunctionToMoveTo ),
+ empty_handler_vtable_ ( emptyFunctionToMoveTo.get_vtable() )
+ {
+ assert( emptyFunctionToMoveTo.pVTable == &empty_handler_vtable_ );
+ move( functionToGuard, emptyFunctionToMoveTo, empty_handler_vtable_ );
+ }
+
+ ~safe_mover_base() {}
+
+public:
+ void cancel() { assert( pFunctionToRestoreTo ); pFunctionToRestoreTo = 0; }
+
+ static void move( function_base & source, function_base & destination, vtable const & empty_handler_vtable )
+ {
+ source.get_vtable().move( source.functor, destination.functor );
+ destination.pVTable = source.pVTable;
+ source.pVTable = &empty_handler_vtable;
+ }
+
+protected:
+ function_base * pFunctionToRestoreTo ;
+ function_base & emptyFunctionToMoveTo_;
+ vtable const & empty_handler_vtable_ ;
+};
+
+
+// ...if the is_stateless<EmptyHandler> requirement sticks this will not need
+// to be a template...
+template <class EmptyHandler>
+class function_base::safe_mover : public safe_mover_base
+{
+public:
+ safe_mover( function_base & functionToGuard, function_base & emptyFunctionToMoveTo )
+ :
+ safe_mover_base( functionToGuard, emptyFunctionToMoveTo ) {}
+ ~safe_mover()
+ {
+ if ( pFunctionToRestoreTo )
+ {
+ cleaner<EmptyHandler> guard( *pFunctionToRestoreTo, empty_handler_vtable_ );
+ move( emptyFunctionToMoveTo_, *pFunctionToRestoreTo, empty_handler_vtable_ );
+ guard.cancel();
+ }
+ }
+};
+
+/// The bad_function_call exception class is thrown when an empty
+/// boost::function object is invoked that uses the throw_on_empty empty
+/// handler.
 class bad_function_call : public std::runtime_error
 {
 public:
   bad_function_call() : std::runtime_error("call to empty boost::function") {}
 };
 
+class throw_on_empty
+{
+private:
+ #ifdef BOOST_MSVC
+ __declspec( noinline noreturn )
+ #endif // BOOST_MSVC
+ void throw_bad_call() const
+ {
+ boost::throw_exception(bad_function_call());
+ }
+
+public:
+ template <class result_type>
+ #ifdef BOOST_MSVC
+ __declspec( noreturn )
+ #endif // BOOST_MSVC
+ result_type operator()() const
+ {
+ throw_bad_call();
+ #ifndef BOOST_MSVC
+ return result_type();
+ #endif // BOOST_MSVC
+ }
+};
+
+class assert_on_empty
+{
+public:
+ template <class result_type>
+ result_type operator()() const
+ {
+ assert( !"call to empty boost::function" );
+ return result_type();
+ }
+};
+
+class nop_on_empty
+{
+public:
+ template <class result_type>
+ result_type operator()() const { return result_type(); }
+};
+
+
+#define BOOST_FUNCTION_ENABLE_IF_FUNCTION \
+ template <class Function> \
+ typename enable_if \
+ < \
+ is_base_of<::boost::function_base, Function>, \
+ bool \
+ >::type
+
 #ifndef BOOST_NO_SFINAE
-inline bool operator==(const function_base& f,
- detail::function::useless_clear_type*)
+BOOST_FUNCTION_ENABLE_IF_FUNCTION
+inline operator==(const Function& f, detail::function::useless_clear_type*)
 {
   return f.empty();
 }
 
-inline bool operator!=(const function_base& f,
- detail::function::useless_clear_type*)
+BOOST_FUNCTION_ENABLE_IF_FUNCTION
+inline operator!=(const Function& f, detail::function::useless_clear_type*)
 {
   return !f.empty();
 }
 
-inline bool operator==(detail::function::useless_clear_type*,
- const function_base& f)
+BOOST_FUNCTION_ENABLE_IF_FUNCTION
+inline operator==(detail::function::useless_clear_type*, const Function& f)
 {
   return f.empty();
 }
 
-inline bool operator!=(detail::function::useless_clear_type*,
- const function_base& f)
+BOOST_FUNCTION_ENABLE_IF_FUNCTION
+inline operator!=(detail::function::useless_clear_type*, const Function& f)
 {
   return !f.empty();
 }
@@ -872,28 +1518,178 @@
 
 namespace detail {
   namespace function {
- inline bool has_empty_target(const function_base* f)
+ BOOST_FUNCTION_ENABLE_IF_FUNCTION
+ inline has_empty_target( Function const * const f )
     {
       return f->empty();
     }
 
-#if BOOST_WORKAROUND(BOOST_MSVC, <= 1310)
- inline bool has_empty_target(const void*)
+ template <class FunctionPtr>
+ inline bool has_empty_target( reference_wrapper<FunctionPtr> const * const f )
     {
- return false;
+ return has_empty_target( f->get_pointer() );
     }
+
+ template <class FunctionPtr>
+ typename enable_if_c
+ <
+ is_pointer <FunctionPtr>::value ||
+ is_function <FunctionPtr>::value ||
+ is_member_function_pointer<FunctionPtr>::value,
+ bool
+ >::type
+ inline has_empty_target( FunctionPtr const * const funcPtr )
+ {
+ return funcPtr == 0;
+ }
+
+#ifdef BOOST_MSVC // MSVC (9.0 SP1 and prior) cannot inline vararg functions
+ inline bool has_empty_target(const void*)
 #else
     inline bool has_empty_target(...)
+#endif
     {
       return false;
     }
-#endif
+
+ /* Just an experiment to show how can the current boost::mem_fn implementation
+ be 'hacked' to work with custom mem_fn pointer holders (in this case a static
+ reference) and/to implement the above. See the assign template overload for
+ member functions in function_template.hpp. */
+ namespace mem_fn_wrapper
+ {
+ #define BOOST_MEM_FN_CLASS_F , class F
+ #define BOOST_MEM_FN_TYPEDEF(X)
+ #define BOOST_MEM_FN_NAME(X) X
+ #define BOOST_MEM_FN_CC
+ #define BOOST_MEM_FN_RETURN return
+
+ #include "boost/bind/mem_fn_template.hpp"
+
+ #undef BOOST_MEM_FN_CLASS_F
+ #undef BOOST_MEM_FN_TYPEDEF
+ #undef BOOST_MEM_FN_NAME
+ #undef BOOST_MEM_FN_CC
+ #undef BOOST_MEM_FN_RETURN
+ }
   } // end namespace function
 } // end namespace detail
 } // end namespace boost
 
 #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
 #undef BOOST_FUNCTION_COMPARE_TYPE_ID
+#undef BOOST_FUNCTION_ENABLE_IF_FUNCTION
+
+// ...to be moved 'somewhere else'...
+namespace boost {
+namespace detail {
+ template <typename T>
+ struct get_non_type_template_parameter_type
+ {
+ typedef typename boost::mpl::eval_if_c
+ <
+ is_integral <T>::value ||
+ is_pointer <T>::value ||
+ is_member_pointer <T>::value ||
+ is_reference <T>::value ||
+ is_function <T>::value ||
+ is_enum <T>::value ||
+ function::is_msvc_exception_specified_function_pointer<T>::value,
+ add_const<T>,
+ add_reference<T>
+ >::type type;
+ };
+} // end namespace detail
+
+template
+<
+ typename T,
+ typename detail::get_non_type_template_parameter_type<T>::type t
+>
+class static_reference_wrapper
+{
+public:
+ typedef typename detail::get_non_type_template_parameter_type<T>::type type;
+
+private:
+ static type * get_pointer( type & t ) { return &t; }
+ static type * get_pointer( type * pt ) { return pt; }
+
+public:
+ operator type () const { return get(); }
+
+ static type get() { return t; }
+
+ static T const * get_pointer()
+ {
+ if ( is_reference<type>::value )
+ return get_pointer( t );
+ else
+ {
+ static add_const<type>::type t_( t );
+ return get_pointer( t_ );
+ }
+ }
+};
+
+template
+<
+ typename T,
+ typename detail::get_non_type_template_parameter_type<T>::type t
+>
+class is_reference_wrapper<static_reference_wrapper<T, t>>
+ : public mpl::true_
+{
+};
+
+template<typename T>
+class is_static_reference_wrapper
+ : public mpl::false_
+{
+};
+
+template
+<
+ typename T,
+ typename detail::get_non_type_template_parameter_type<T>::type t
+>
+class is_static_reference_wrapper<static_reference_wrapper<T, t>>
+ : public mpl::true_
+{
+};
+
+namespace detail {
+ template
+ <
+ typename T,
+ // this has to be placed here and not in the struct body because that
+ // kills msvc
+ typename StorageType = typename get_non_type_template_parameter_type<T>::type
+ >
+ struct static_reference_maker : public boost::reference_wrapper<T>
+ {
+ explicit static_reference_maker( T & t ) : reference_wrapper<T>( t ) {}
+
+ template <StorageType object_to_reference>
+ static static_reference_wrapper<T, object_to_reference> sref() { return static_reference_wrapper<T, object_to_reference>(); }
+ };
+} // end namespace detail
+
+template <typename T>
+detail::static_reference_maker<T> sref( T & t )
+{
+ return detail::static_reference_maker<T>( t );
+}
+
+template <typename T>
+detail::static_reference_maker<T const> sref( T const & t )
+{
+ return detail::static_reference_maker<T const>( t );
+}
+
+#define BOOST_SREF( object ) boost::sref( object ).sref<object>()
+
+} // end namespace boost
 
 #if defined(BOOST_MSVC)
 # pragma warning( pop )

Modified: sandbox/function/boost/function/function_fwd.hpp
==============================================================================
--- sandbox/function/boost/function/function_fwd.hpp (original)
+++ sandbox/function/boost/function/function_fwd.hpp 2009-12-17 11:35:23 EST (Thu, 17 Dec 2009)
@@ -9,6 +9,7 @@
 #ifndef BOOST_FUNCTION_FWD_HPP
 #define BOOST_FUNCTION_FWD_HPP
 #include <boost/config.hpp>
+#include <boost/mpl/map.hpp>
 
 #if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
 // Work around a compiler bug.
@@ -27,43 +28,53 @@
 
 namespace boost {
   class bad_function_call;
+ class assert_on_empty;
+ class throw_on_empty;
+ struct EmptyHandler {};
+ struct Nothrow {};
+
+ struct default_policies : public mpl::map2
+ <
+ mpl::pair<EmptyHandler, throw_on_empty>,
+ mpl::pair<Nothrow , mpl::false_ >
+ > {};
 
 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
   // Preferred syntax
- template<typename Signature> class function;
+ template<typename Signature, class PolicyList = default_policies> class function;
 
- template<typename Signature>
- inline void swap(function<Signature>& f1, function<Signature>& f2)
+ template<typename Signature, class PolicyList>
+ inline void swap(function<Signature, PolicyList>& f1, function<Signature, PolicyList>& f2)
   {
     f1.swap(f2);
   }
 #endif // have partial specialization
 
   // Portable syntax
- template<typename R> class function0;
- template<typename R, typename T1> class function1;
- template<typename R, typename T1, typename T2> class function2;
- template<typename R, typename T1, typename T2, typename T3> class function3;
- template<typename R, typename T1, typename T2, typename T3, typename T4>
+ template<typename R, class PolicyList = default_policies> class function0;
+ template<typename R, typename T1, class PolicyList = default_policies> class function1;
+ template<typename R, typename T1, typename T2, class PolicyList = default_policies> class function2;
+ template<typename R, typename T1, typename T2, typename T3, class PolicyList = default_policies> class function3;
+ template<typename R, typename T1, typename T2, typename T3, typename T4, class PolicyList = default_policies>
     class function4;
   template<typename R, typename T1, typename T2, typename T3, typename T4,
- typename T5>
+ typename T5, class PolicyList = default_policies>
     class function5;
   template<typename R, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6>
+ typename T5, typename T6, class PolicyList = default_policies>
     class function6;
   template<typename R, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7>
+ typename T5, typename T6, typename T7, class PolicyList = default_policies>
     class function7;
   template<typename R, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7, typename T8>
+ typename T5, typename T6, typename T7, typename T8, class PolicyList = default_policies>
     class function8;
   template<typename R, typename T1, typename T2, typename T3, typename T4,
- typename T5, typename T6, typename T7, typename T8, typename T9>
+ typename T5, typename T6, typename T7, typename T8, typename T9, class PolicyList = default_policies>
     class function9;
   template<typename R, typename T1, typename T2, typename T3, typename T4,
            typename T5, typename T6, typename T7, typename T8, typename T9,
- typename T10>
+ typename T10, class PolicyList = default_policies>
     class function10;
 }
 

Modified: sandbox/function/boost/function/function_template.hpp
==============================================================================
--- sandbox/function/boost/function/function_template.hpp (original)
+++ sandbox/function/boost/function/function_template.hpp 2009-12-17 11:35:23 EST (Thu, 17 Dec 2009)
@@ -15,7 +15,14 @@
 
 #if defined(BOOST_MSVC)
 # pragma warning( push )
+# pragma warning( disable : 4100 ) // "unreferenced formal parameter" (for
+ // base_empty_handler::operator() that
+ // ignores all of its parameters
 # pragma warning( disable : 4127 ) // "conditional expression is constant"
+# pragma warning( disable : 4512 ) // "assignment operator could not be generated" (exact_signature_mem_invoker)
+# pragma warning( disable : 4702 ) // "unreachable code" (when calling return
+ // base_empty_handler::operator() when that
+ // operator does not return (throws)
 #endif
 
 #define BOOST_FUNCTION_TEMPLATE_PARMS BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS, typename T)
@@ -42,33 +49,10 @@
 
 // Class names used in this version of the code
 #define BOOST_FUNCTION_FUNCTION BOOST_JOIN(function,BOOST_FUNCTION_NUM_ARGS)
-#define BOOST_FUNCTION_FUNCTION_INVOKER \
- BOOST_JOIN(function_invoker,BOOST_FUNCTION_NUM_ARGS)
-#define BOOST_FUNCTION_VOID_FUNCTION_INVOKER \
- BOOST_JOIN(void_function_invoker,BOOST_FUNCTION_NUM_ARGS)
 #define BOOST_FUNCTION_FUNCTION_OBJ_INVOKER \
   BOOST_JOIN(function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
 #define BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER \
   BOOST_JOIN(void_function_obj_invoker,BOOST_FUNCTION_NUM_ARGS)
-#define BOOST_FUNCTION_FUNCTION_REF_INVOKER \
- 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(function_mem_invoker,BOOST_FUNCTION_NUM_ARGS)
-#define BOOST_FUNCTION_VOID_MEMBER_INVOKER \
- BOOST_JOIN(function_void_mem_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
 # define BOOST_FUNCTION_VOID_RETURN_TYPE void
@@ -81,573 +65,63 @@
 namespace boost {
   namespace detail {
     namespace function {
- template<
- typename FunctionPtr,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_FUNCTION_INVOKER
- {
- static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_PARMS)
- {
- FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
- return f(BOOST_FUNCTION_ARGS);
- }
- };
-
- template<
- typename FunctionPtr,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER
- {
- static BOOST_FUNCTION_VOID_RETURN_TYPE
- invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_PARMS)
-
- {
- FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr);
- BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
- }
- };
-
- template<
- typename FunctionObj,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
- {
- static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_PARMS)
-
- {
- FunctionObj* f;
- if (function_allows_small_object_optimization<FunctionObj>::value)
- f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
- else
- f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
- return (*f)(BOOST_FUNCTION_ARGS);
- }
- };
 
- template<
+ template
+ <
         typename FunctionObj,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
- {
- static BOOST_FUNCTION_VOID_RETURN_TYPE
- invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_PARMS)
-
- {
- FunctionObj* f;
- if (function_allows_small_object_optimization<FunctionObj>::value)
- f = reinterpret_cast<FunctionObj*>(&function_obj_ptr.data);
- else
- f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
- BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
+ typename FunctionObjManager,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER : public function_buffer_holder
+ {
+ R invoke( BOOST_FUNCTION_PARMS )
+ {
+ // We provide the invoker with a manager with a minimum amount of
+ // type information (because it already knows the stored function
+ // object it works with, it only needs to get its address from a
+ // function_buffer object). Because of this we must cast the pointer
+ // returned by FunctionObjManager::functor_ptr() because it can be
+ // a plain void * in case of the trivial managers. In case of the
+ // trivial ptr manager it is even a void * * so a double static_cast
+ // (or a reinterpret_cast) is necessary.
+ FunctionObj & functionObject
+ (
+ *static_cast<FunctionObj *>
+ (
+ static_cast<void *>
+ (
+ FunctionObjManager::functor_ptr( buffer )
+ )
+ )
+ );
+ // unwrap_ref is needed because boost::reference_wrapper<T>, unlike
+ // the one from std::tr1, does not support callable objects
+ return unwrap_ref( functionObject )( BOOST_FUNCTION_ARGS );
         }
       };
 
- template<
+ template
+ <
         typename FunctionObj,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
+ typename FunctionObjManager,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS
>
- struct BOOST_FUNCTION_FUNCTION_REF_INVOKER
- {
- static R invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_PARMS)
-
- {
- FunctionObj* f =
- reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
- return (*f)(BOOST_FUNCTION_ARGS);
- }
- };
-
- template<
- typename FunctionObj,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER
- {
- static BOOST_FUNCTION_VOID_RETURN_TYPE
- invoke(function_buffer& function_obj_ptr BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_PARMS)
-
- {
- FunctionObj* f =
- reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
- BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
- }
- };
-
-#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
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_GET_FUNCTION_INVOKER
- {
- typedef typename mpl::if_c<(is_void<R>::value),
- BOOST_FUNCTION_VOID_FUNCTION_INVOKER<
- FunctionPtr,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >,
- BOOST_FUNCTION_FUNCTION_INVOKER<
- FunctionPtr,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >
- >::type type;
- };
-
- template<
- typename FunctionObj,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER
- {
- typedef typename mpl::if_c<(is_void<R>::value),
- BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER<
- FunctionObj,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >,
- BOOST_FUNCTION_FUNCTION_OBJ_INVOKER<
- FunctionObj,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >
- >::type type;
- };
-
- template<
- typename FunctionObj,
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
- >
- struct BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER
- {
- typedef typename mpl::if_c<(is_void<R>::value),
- BOOST_FUNCTION_VOID_FUNCTION_REF_INVOKER<
- FunctionObj,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >,
- BOOST_FUNCTION_FUNCTION_REF_INVOKER<
- FunctionObj,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >
- >::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>
+ struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER : public function_buffer_holder
       {
- template<typename FunctionPtr,
- typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
- 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> manager_type;
- };
-
- template<typename FunctionPtr,
- typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
- struct apply_a
- {
- typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
- FunctionPtr,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- invoker_type;
-
- typedef functor_manager<FunctionPtr> 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>
- 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> manager_type;
- };
-
- template<typename MemberPtr,
- typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
- struct apply_a
- {
- typedef typename BOOST_FUNCTION_GET_MEMBER_INVOKER<
- MemberPtr,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- invoker_type;
-
- typedef functor_manager<MemberPtr> 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>
- 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> manager_type;
- };
-
- template<typename FunctionObj,
- typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
- struct apply_a
- {
- typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
- FunctionObj,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- invoker_type;
-
- typedef functor_manager_a<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>
- 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;
- };
-
- template<typename RefWrapper,
- typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
- typename Allocator>
- struct apply_a
- {
- 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. This
- * structure must be an aggregate so that we can use static
- * initialization in boost::function's assign_to and assign_to_a
- * members. It therefore cannot have any constructors,
- * destructors, base classes, etc.
- */
- template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
- struct BOOST_FUNCTION_VTABLE
- {
-#ifndef BOOST_NO_VOID_RETURNS
- typedef R result_type;
-#else
- typedef typename function_return_type<R>::type result_type;
-#endif // BOOST_NO_VOID_RETURNS
-
- typedef result_type (*invoker_type)(function_buffer&
- BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS);
-
- 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)
- {
- if (base.manager)
- base.manager(functor, functor, destroy_functor_tag);
- }
-
- private:
- // Function pointers
- template<typename FunctionPtr>
- bool
- assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
- {
- this->clear(functor);
- if (f) {
- // should be a reinterpret cast, but some compilers insist
- // on giving cv-qualifiers to free functions
- functor.func_ptr = (void (*)())(f);
- return true;
- } else {
- 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)
- {
- // 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;
+ BOOST_FUNCTION_VOID_RETURN_TYPE invoke(BOOST_FUNCTION_PARMS)
+ {
+ // see the above comments for the non-void invoker
+ FunctionObj & functionObject( *static_cast<FunctionObj *>( static_cast<void *>( FunctionObjManager::functor_ptr( buffer ) ) ) );
+ BOOST_FUNCTION_RETURN( unwrap_ref( functionObject )( BOOST_FUNCTION_ARGS ) );
           }
- }
- 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) {
- this->assign_to_a(mem_fn(f), functor, a);
- return true;
- } else {
- return false;
- }
- }
-#endif // BOOST_FUNCTION_NUM_ARGS > 0
-
- // Function objects
- // Assign to a function object using the small object optimization
- template<typename FunctionObj>
- void
- 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(FunctionObj f, function_buffer& functor, mpl::false_)
- {
- functor.obj_ptr = new FunctionObj(f);
- }
- 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(FunctionObj f, function_buffer& functor, function_obj_tag)
- {
- if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
- assign_functor(f, functor,
- mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
- return true;
- } else {
- 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>
- bool
- assign_to(const reference_wrapper<FunctionObj>& f,
- function_buffer& functor, function_obj_ref_tag)
- {
- functor.obj_ref.obj_ptr = (void *)f.get_pointer();
- functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
- functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
- return true;
- }
- 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
   } // end namespace detail
 
- template<
- typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS
+ template
+ <
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS,
+ class PolicyList
>
   class BOOST_FUNCTION_FUNCTION : public function_base
 
@@ -662,27 +136,22 @@
 #endif
 
   {
- public:
+ private: // Actual policies deduction section.
+ //mpl::at<AssocSeq,Key,Default> does not yet exist so...:
+ typedef typename mpl::at<PolicyList , EmptyHandler>::type user_specified_empty_handler;
+ typedef typename mpl::at<default_policies, EmptyHandler>::type default_empty_handler;
+
+ typedef typename mpl::at<PolicyList , Nothrow>::type user_specified_nothrow_policy;
+ typedef typename mpl::at<default_policies, Nothrow>::type default_nothrow_policy;
+
+ public: // Public typedefs/introspection section.
 #ifndef BOOST_NO_VOID_RETURNS
     typedef R result_type;
 #else
- typedef typename boost::detail::function::function_return_type<R>::type
+ typedef typename boost::detail::function::function_return_type<R>::type
       result_type;
 #endif // BOOST_NO_VOID_RETURNS
 
- private:
- typedef boost::detail::function::BOOST_FUNCTION_VTABLE<
- R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
- vtable_type;
-
- vtable_type* get_vtable() const {
- return reinterpret_cast<vtable_type*>(
- reinterpret_cast<std::size_t>(vtable) & ~(std::size_t)0x01);
- }
-
- struct clear_type {};
-
- public:
     BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
 
     // add signature for boost::lambda
@@ -704,7 +173,54 @@
 
     typedef BOOST_FUNCTION_FUNCTION self_type;
 
- BOOST_FUNCTION_FUNCTION() : function_base() { }
+ typedef typename mpl::if_
+ <
+ is_same<user_specified_empty_handler, mpl::void_>,
+ default_empty_handler,
+ user_specified_empty_handler
+ >::type base_empty_handler;
+
+ BOOST_STATIC_ASSERT( is_stateless<base_empty_handler>::value );
+
+ // The nothrow policy and runtime throw detection functionality works only in
+ // release mode/with optimizations on. It should also work in debug for plain
+ // function pointers with compilers that properly implement the 'exception
+ // specification shadow type system' (MSVC 9.0 SP1 does not) - this path yet
+ // needs to be tested and properly (re)implemented.
+ #ifndef _DEBUG
+ typedef typename mpl::if_
+ <
+ is_same<user_specified_nothrow_policy, mpl::void_>,
+ default_nothrow_policy,
+ user_specified_nothrow_policy
+ >::type nothrow_policy;
+ #else
+ typedef mpl::false_ nothrow_policy;
+ #endif
+
+ typedef R signature_type ( BOOST_FUNCTION_TEMPLATE_ARGS );
+
+ private: // Private implementation types.
+ // We need a specific thin wrapper around the base empty handler that will
+ // just consume all the parameters. This way the base empty handler can have
+ // one plain simple operator(). As part of ant-code-bloat measures,
+ // my_empty_handler is used only when really necessary (with the invoker),
+ // otherwise the base_empty_handler type is used.
+ struct my_empty_handler : public base_empty_handler
+ {
+ R operator()( BOOST_FUNCTION_PARMS ) const
+ {
+ return base_empty_handler::operator()<R>();
+ }
+ };
+
+ typedef detail::function::vtable vtable_type;
+
+ struct clear_type {};
+
+ public: // Public function interface.
+
+ BOOST_FUNCTION_FUNCTION() : function_base( empty_handler_vtable() ) {}
 
     // MSVC chokes if the following two constructors are collapsed into
     // one with a default parameter.
@@ -717,10 +233,12 @@
                                         int>::type = 0
 #endif // BOOST_NO_SFINAE
                             ) :
- function_base()
+ function_base( empty_handler_vtable() )
     {
- this->assign_to(f);
+ this->do_assign<true, Functor>( f );
     }
+
+/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
     template<typename Functor,typename Allocator>
     BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a
 #ifndef BOOST_NO_SFINAE
@@ -730,47 +248,96 @@
                                         int>::type = 0
 #endif // BOOST_NO_SFINAE
                             ) :
- function_base()
+ function_base( empty_handler_vtable() )
     {
       this->assign_to_a(f,a);
     }
+*/
 
 #ifndef BOOST_NO_SFINAE
- BOOST_FUNCTION_FUNCTION(clear_type*) : function_base() { }
+ BOOST_FUNCTION_FUNCTION(clear_type*) : function_base( empty_handler_vtable() ) { }
 #else
- BOOST_FUNCTION_FUNCTION(int zero) : function_base()
+ BOOST_FUNCTION_FUNCTION(int zero) : function_base( empty_handler_vtable() )
     {
       BOOST_ASSERT(zero == 0);
     }
 #endif
 
- BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base()
+ BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : function_base( empty_handler_vtable() )
+ {
+ this->do_assign<true>( f );
+ }
+
+ /// Determine if the function is empty (i.e., has empty target).
+ bool empty() const { return pVTable == &empty_handler_vtable(); }
+
+ /// Clear out a target (replace it with an empty handler), if there is one.
+ void clear()
+ {
+ function_base::clear<base_empty_handler>( empty_handler_vtable() );
+ }
+
+ template<typename FunctionObj>
+ void assign( FunctionObj const & f )
+ {
+ this->do_assign<false, FunctionObj>( f );
+ }
+
+ template <signature_type * f>
+ void assign()
     {
- this->assign_to_own(f);
+ this->assign( detail::static_reference_maker<signature_type *>::sref<f>() );
     }
 
- ~BOOST_FUNCTION_FUNCTION() { clear(); }
+ template <class AClass, R (AClass::*mmf)(BOOST_FUNCTION_TEMPLATE_ARGS)>
+ void assign( AClass & object )
+ {
+ class exact_signature_mem_invoker
+ {
+ public:
+ exact_signature_mem_invoker( AClass & object ) : object( object ) {}
+ result_type operator()( BOOST_FUNCTION_PARMS ) const { return (object.*mmf)( BOOST_FUNCTION_ARGS ); }
+ private:
+ AClass & object;
+ };
+ this->assign( exact_signature_mem_invoker( object ) );
+
+/* Just an experiment to show how can the current boost::mem_fn implementation
+ be 'hacked' to work with custom mem_fn pointer holders (in this case a static
+ reference) and/to implement the above.
+ typedef static_reference_wrapper
+ <
+ R (AClass::*)(BOOST_FUNCTION_TEMPLATE_ARGS),
+ mmf
+ > static_mem_fn_reference;
+
+ typedef BOOST_JOIN( detail::function::mem_fn_wrapper::mf, BOOST_FUNCTION_NUM_ARGS )
+ <
+ R,
+ AClass
+ BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS,
+ static_mem_fn_reference
+ > mem_fn_wrapper;
+
+ this->assign( bind( mem_fn_wrapper( static_mem_fn_reference() ), &object, _1 ) );
+*/
+ }
 
-#if BOOST_WORKAROUND(BOOST_MSVC, < 1300)
- // MSVC 6.0 and prior require all definitions to be inline, but
- // these definitions can become very costly.
     result_type operator()(BOOST_FUNCTION_PARMS) const
     {
- if (this->empty())
- boost::throw_exception(bad_function_call());
+ return invoke( BOOST_FUNCTION_ARGS BOOST_FUNCTION_COMMA nothrow_policy() );
+ }
+
 
- return get_vtable()->invoker
- (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
+ // ...this one is perhaps no longer needed (the one below can probably "take
+ // over"...
+ BOOST_FUNCTION_FUNCTION & operator=( BOOST_FUNCTION_FUNCTION const & f )
+ {
+ this->assign( f )
+ return *this;
     }
-#else
- result_type operator()(BOOST_FUNCTION_PARMS) const;
-#endif
 
- // The distinction between when to use BOOST_FUNCTION_FUNCTION and
- // when to use self_type is obnoxious. MSVC cannot handle self_type as
- // the return type of these assignment operators, but Borland C++ cannot
- // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
- // construct.
     template<typename Functor>
 #ifndef BOOST_NO_SFINAE
     typename enable_if_c<
@@ -782,28 +349,17 @@
 #endif
     operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f)
     {
- this->clear();
- BOOST_TRY {
- this->assign_to(f);
- } BOOST_CATCH (...) {
- vtable = 0;
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
+ this->assign(f);
       return *this;
     }
+
+/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
     template<typename Functor,typename Allocator>
     void assign(Functor BOOST_FUNCTION_TARGET_FIX(const &) f, Allocator a)
     {
- this->clear();
- BOOST_TRY{
- this->assign_to_a(f,a);
- } BOOST_CATCH (...) {
- vtable = 0;
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
+ this->assign_to_a(f,a);
     }
+*/
 
 #ifndef BOOST_NO_SFINAE
     BOOST_FUNCTION_FUNCTION& operator=(clear_type*)
@@ -820,111 +376,137 @@
     }
 #endif
 
- // Assignment from another BOOST_FUNCTION_FUNCTION
- BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f)
- {
- if (&f == this)
- return *this;
-
- this->clear();
- BOOST_TRY {
- this->assign_to_own(f);
- } BOOST_CATCH (...) {
- vtable = 0;
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
- return *this;
- }
-
     void swap(BOOST_FUNCTION_FUNCTION& other)
     {
- if (&other == this)
- return;
-
- BOOST_FUNCTION_FUNCTION tmp;
- tmp.move_assign(*this);
- this->move_assign(other);
- other.move_assign(tmp);
- }
-
- // Clear out a target, if there is one
- void clear()
- {
- if (vtable) {
- if (!this->has_trivial_copy_and_destroy())
- get_vtable()->clear(this->functor);
- vtable = 0;
- }
+ BOOST_STATIC_ASSERT( sizeof( BOOST_FUNCTION_FUNCTION ) == sizeof( function_base ) );
+ return function_base::swap<base_empty_handler>( other, empty_handler_vtable() );
     }
 
 #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
     // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
     operator bool () const { return !this->empty(); }
 #else
- private:
- struct dummy {
- void nonnull() {};
- };
-
- typedef void (dummy::*safe_bool)();
-
   public:
     operator safe_bool () const
       { return (this->empty())? 0 : &dummy::nonnull; }
 
- bool operator!() const
- { return this->empty(); }
+ bool operator!() const { return this->empty(); }
 #endif
 
- private:
- void assign_to_own(const BOOST_FUNCTION_FUNCTION& f)
+private:
+ static vtable_type const & empty_handler_vtable() { return vtable_for_functor<base_empty_handler>( my_empty_handler() ); }
+
+ template <class F>
+ static bool nothrow_test( F & f BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS )
     {
- if (!f.empty()) {
- this->vtable = f.vtable;
- if (this->has_trivial_copy_and_destroy())
- this->functor = f.functor;
- else
- get_vtable()->base.manager(f.functor, this->functor,
- boost::detail::function::clone_functor_tag);
- }
+ f( BOOST_FUNCTION_ARGS );
+ return true;
     }
 
- template<typename Functor>
- void assign_to(Functor f)
+ template <class F>
+ static bool throw_test( F & f BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS )
     {
- using detail::function::vtable_base;
+ try
+ {
+ f( BOOST_FUNCTION_ARGS );
+ return true;
+ }
+ catch(...)
+ {
+ return false;
+ }
+ }
 
- 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>
- handler_type;
-
- typedef typename handler_type::invoker_type invoker_type;
- typedef typename handler_type::manager_type manager_type;
+ template <class F>
+ static bool is_nothrow()
+ {
+ typedef bool ( throw_test_signature ) ( unwrap_reference<F>::type & BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS );
+ return detail::function::is_nothrow_helper
+ <
+ throw_test_signature,
+ &nothrow_test<unwrap_reference<F>::type>,
+ &throw_test <unwrap_reference<F>::type>
+ >::is_nothrow;
+ }
+
+
+ #ifdef BOOST_MSVC
+ __declspec( nothrow )
+ #endif
+ result_type invoke(BOOST_FUNCTION_PARMS BOOST_FUNCTION_COMMA mpl::true_ /*no throw invoker*/) const
+ #ifndef BOOST_MSVC
+ throw()
+ #endif
+ {
+ typedef result_type (detail::function::function_buffer_holder::* invoker_type)(BOOST_FUNCTION_TEMPLATE_ARGS);
+ return (reinterpret_cast<detail::function::function_buffer_holder &>( this->functor ).*get_vtable().invoker<invoker_type>())
+ (BOOST_FUNCTION_ARGS);
+ }
+
+ result_type invoke(BOOST_FUNCTION_PARMS BOOST_FUNCTION_COMMA mpl::false_ /*throwable invoker*/) const
+ {
+ typedef result_type (detail::function::function_buffer_holder::* invoker_type)(BOOST_FUNCTION_TEMPLATE_ARGS);
+ return (reinterpret_cast<detail::function::function_buffer_holder &>( this->functor ).*get_vtable().invoker<invoker_type>())
+ (BOOST_FUNCTION_ARGS);
+ }
+
+ template <typename ActualFunctor, typename StoredFunctor>
+ typename enable_if<is_base_of<function_base, StoredFunctor>, vtable_type const &>::type
+ static vtable_for_functor( StoredFunctor const & functor )
+ {
+ return functor.get_vtable();
+ }
+
+ template <typename ActualFunctor, typename StoredFunctor>
+ typename disable_if<is_base_of<function_base, StoredFunctor>, vtable_type const &>::type
+ static vtable_for_functor( StoredFunctor const & /*functor*/ )
+ {
+ using namespace detail::function;
+
+ // A minimally typed manager is used for the invoker (anti-code-bloat).
+ typedef typename get_functor_manager
+ <
+ StoredFunctor
+ >::type invoker_manager_type;
+
+ // For the empty handler we use the manager for the base_empty_handler not
+ // my_empty_handler (anti-code-bloat) because they only differ in the
+ // operator() member function which is irrelevant for/not used by the
+ // manager.
+ typedef typename get_typed_functor_manager
+ <
+ ActualFunctor,
+ typename mpl::if_
+ <
+ is_same<ActualFunctor, base_empty_handler>,
+ ActualFunctor,
+ StoredFunctor
+ >::type
+ >::type manager_type;
+
+ typedef typename mpl::if_
+ <
+ is_void<R>,
+ BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER
+ <
+ StoredFunctor,
+ invoker_manager_type,
+ R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS
+ >,
+ BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
+ <
+ StoredFunctor,
+ invoker_manager_type,
+ R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS
+ >
+ >::type invoker_type;
 
- // Note: it is extremely important that this initialization use
- // static initialization. Otherwise, we will have a race
- // condition here in multi-threaded code. See
- // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
- static vtable_type stored_vtable =
- { { &manager_type::manage }, &invoker_type::invoke };
-
- if (stored_vtable.assign_to(f, functor)) {
- std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
- if (boost::has_trivial_copy_constructor<Functor>::value &&
- boost::has_trivial_destructor<Functor>::value &&
- detail::function::function_allows_small_object_optimization<Functor>::value)
- value |= (std::size_t)0x01;
- vtable = reinterpret_cast<detail::function::vtable_base *>(value);
- } else
- vtable = 0;
+ return vtable_holder<invoker_type, manager_type>::stored_vtable;
     }
 
+/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
     template<typename Functor,typename Allocator>
- void assign_to_a(Functor f,Allocator a)
+ static vtable_type const & vtable_for_functor_a()
     {
       using detail::function::vtable_base;
 
@@ -936,53 +518,83 @@
                          Allocator>
         handler_type;
       
- typedef typename handler_type::invoker_type invoker_type;
- typedef typename handler_type::manager_type manager_type;
-
- // Note: it is extremely important that this initialization use
- // static initialization. Otherwise, we will have a race
- // condition here in multi-threaded code. See
- // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
- static vtable_type stored_vtable =
- { { &manager_type::manage }, &invoker_type::invoke };
-
- if (stored_vtable.assign_to_a(f, functor, a)) {
- std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
- if (boost::has_trivial_copy_constructor<Functor>::value &&
- boost::has_trivial_destructor<Functor>::value &&
- detail::function::function_allows_small_object_optimization<Functor>::value)
- value |= (std::size_t)0x01;
- vtable = reinterpret_cast<detail::function::vtable_base *>(value);
- } else
- vtable = 0;
- }
-
- // Moves the value from the specified argument to *this. If the argument
- // has its function object allocated on the heap, move_assign will pass
- // its buffer to *this, and set the argument's buffer pointer to NULL.
- void move_assign(BOOST_FUNCTION_FUNCTION& f)
- {
- if (&f == this)
- return;
-
- BOOST_TRY {
- if (!f.empty()) {
- this->vtable = f.vtable;
- if (this->has_trivial_copy_and_destroy())
- this->functor = f.functor;
- else
- get_vtable()->base.manager(f.functor, this->functor,
- boost::detail::function::move_functor_tag);
- f.vtable = 0;
- } else {
- clear();
+ typedef typename handler_type::invoker_type invoker_type;
+ typedef typename boost::mpl::if_
+ <
+ boost::is_base_of<base_empty_handler, Functor>,
+ detail::function::functor_manager<base_empty_handler>,
+ detail::function::functor_manager_a<Functor, Allocator>
+ >::type manager_type;
+
+ return static_cast<vtable_type const &>( detail::function::vtable_holder<invoker_type, manager_type>::stored_vtable );
+ }
+*/
+ // ...direct actually means whether to skip pre-destruction (when not
+ // assigning but constructing) so it should probably be renamed to
+ // pre_destroy or the whole thing solved in some smarter way...
+ template<bool direct, typename FunctionObj>
+ void do_assign( FunctionObj const & f )
+ {
+ typedef typename detail::function::get_function_tag<FunctionObj>::type tag;
+ dispatch_assign<direct, FunctionObj>( f, tag() );
+ }
+
+ template<bool direct, typename FunctionObj>
+ void dispatch_assign( FunctionObj const & f, detail::function::function_obj_tag ) { do_assign<direct, FunctionObj >( f , f ); }
+ template<bool direct, typename FunctionObj>
+ void dispatch_assign( FunctionObj const & f, detail::function::function_ptr_tag ) { do_assign<direct, FunctionObj >( f , f ); }
+ // DPG TBD: Add explicit support for member function
+ // objects, so we invoke through mem_fn() but we retain the
+ // right target_type() values.
+ template<bool direct, typename FunctionObj>
+ void dispatch_assign( FunctionObj const & f, detail::function::member_ptr_tag ) { do_assign<direct, FunctionObj >( f , mem_fn( f ) ); }
+ template<bool direct, typename FunctionObj>
+ void dispatch_assign( FunctionObj const & f, detail::function::function_obj_ref_tag ) { do_assign<direct, typename FunctionObj::type>( f.get(), f ); }
+
+ template<bool direct, typename ActualFunctor, typename StoredFunctor>
+ void do_assign( ActualFunctor const & original_functor, StoredFunctor const & stored_functor )
+ {
+ if
+ (
+ ( nothrow_policy::value == true ) &&
+ // Assume other copies of the same type of boost::function did
+ // their job in detecting (no)throw function objects.
+ // This function-object-type-specific detection should probably
+ // be moved into the tag dispatched assigns (where 'exception
+ // specification shadow type system' detection for function
+ // pointer should be implemented also).
+ ( !is_base_of<BOOST_FUNCTION_FUNCTION, ActualFunctor>::value ) &&
+ ( !is_nothrow<StoredFunctor>() )
+ )
+ {
+ // This implementation inserts two calls to destroy() (the one here
+ // for the clear and the one, for the else case, further down in
+ // assign) when the nothrow policy is specified...this should be
+ // fixed...
+ assert( is_nothrow<my_empty_handler>() );
+ base_empty_handler const emptyHandler;
+ function_base::assign<direct, base_empty_handler>
+ (
+ emptyHandler,
+ empty_handler_vtable(),
+ empty_handler_vtable()
+ );
+ emptyHandler.operator()<R>();
         }
- } BOOST_CATCH (...) {
- vtable = 0;
- BOOST_RETHROW;
- }
- BOOST_CATCH_END
+ else
+ function_base::assign<direct, base_empty_handler>
+ (
+ stored_functor,
+ vtable_for_functor<ActualFunctor>( stored_functor ),
+ empty_handler_vtable()
+ );
     }
+
+
+/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
+ template<typename Functor,typename Allocator>
+ void assign_to_a(Functor f,Allocator a) { assert( !"Implement" ); }
+*/
   };
 
   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
@@ -998,22 +610,6 @@
     f1.swap(f2);
   }
 
-#if !BOOST_WORKAROUND(BOOST_MSVC, < 1300)
- template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
- typename BOOST_FUNCTION_FUNCTION<
- R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>::result_type
- inline
- 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 get_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>
   void operator==(const BOOST_FUNCTION_FUNCTION<
@@ -1033,27 +629,26 @@
 #if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
 
 #if BOOST_FUNCTION_NUM_ARGS == 0
-#define BOOST_FUNCTION_PARTIAL_SPEC R (void)
+#define BOOST_FUNCTION_PARTIAL_SPEC R (void), PolicyList
 #else
-#define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T))
+#define BOOST_FUNCTION_PARTIAL_SPEC R (BOOST_PP_ENUM_PARAMS(BOOST_FUNCTION_NUM_ARGS,T)), PolicyList
 #endif
 
 template<typename R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_PARMS>
+ BOOST_FUNCTION_TEMPLATE_PARMS, class PolicyList>
 class function<BOOST_FUNCTION_PARTIAL_SPEC>
- : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS>
+ : public BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, PolicyList>
 {
- typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS> base_type;
+ typedef BOOST_FUNCTION_FUNCTION<R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, PolicyList> base_type;
   typedef function self_type;
 
   struct clear_type {};
 
 public:
-
- function() : base_type() {}
+ function() {}
 
   template<typename Functor>
- function(Functor f
+ function(Functor const & f
 #ifndef BOOST_NO_SFINAE
            ,typename enable_if_c<
                             (boost::type_traits::ice_not<
@@ -1064,6 +659,7 @@
     base_type(f)
   {
   }
+/* ALLOCATOR SUPPORT TEMPORARILY COMMENTED OUT
   template<typename Functor,typename Allocator>
   function(Functor f, Allocator a
 #ifndef BOOST_NO_SFINAE
@@ -1076,7 +672,7 @@
     base_type(f,a)
   {
   }
-
+*/
 #ifndef BOOST_NO_SFINAE
   function(clear_type*) : base_type() {}
 #endif
@@ -1085,10 +681,15 @@
 
   function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
 
+ // The distinction between when to use BOOST_FUNCTION_FUNCTION and
+ // when to use self_type is obnoxious. MSVC cannot handle self_type as
+ // the return type of these assignment operators, but Borland C++ cannot
+ // handle BOOST_FUNCTION_FUNCTION as the type of the temporary to
+ // construct.
   self_type& operator=(const self_type& f)
   {
- self_type(f).swap(*this);
- return *this;
+ this->assign( f );
+ return *this;
   }
 
   template<typename Functor>
@@ -1100,9 +701,9 @@
 #else
   self_type&
 #endif
- operator=(Functor f)
+ operator=(Functor const & f)
   {
- self_type(f).swap(*this);
+ this->assign<Functor>( f );
     return *this;
   }
 
@@ -1113,12 +714,6 @@
     return *this;
   }
 #endif
-
- self_type& operator=(const base_type& f)
- {
- self_type(f).swap(*this);
- return *this;
- }
 };
 
 #undef BOOST_FUNCTION_PARTIAL_SPEC
@@ -1127,22 +722,10 @@
 } // end namespace boost
 
 // Cleanup after ourselves...
-#undef BOOST_FUNCTION_VTABLE
 #undef BOOST_FUNCTION_COMMA
 #undef BOOST_FUNCTION_FUNCTION
-#undef BOOST_FUNCTION_FUNCTION_INVOKER
-#undef BOOST_FUNCTION_VOID_FUNCTION_INVOKER
 #undef BOOST_FUNCTION_FUNCTION_OBJ_INVOKER
 #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_MEM_FUNCTION_INVOKER
-#undef BOOST_FUNCTION_GET_INVOKER
 #undef BOOST_FUNCTION_TEMPLATE_PARMS
 #undef BOOST_FUNCTION_TEMPLATE_ARGS
 #undef BOOST_FUNCTION_PARMS


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