Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r49361 - in branches/release: boost/function libs/function/doc libs/function/test
From: dgregor_at_[hidden]
Date: 2008-10-16 09:21:51


Author: dgregor
Date: 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
New Revision: 49361
URL: http://svn.boost.org/trac/boost/changeset/49361

Log:
Merge Boost.Function fixes from trunk
Added:
   branches/release/boost/function/function_fwd.hpp (contents, props changed)
   branches/release/boost/function/function_typeof.hpp (contents, props changed)
   branches/release/libs/function/test/function_typeof_test.cpp (contents, props changed)
   branches/release/libs/function/test/nothrow_swap.cpp (contents, props changed)
Text files modified:
   branches/release/boost/function/function_base.hpp | 178 +++++++++------
   branches/release/boost/function/function_template.hpp | 445 +++++++++++++++++++++++++++------------
   branches/release/libs/function/doc/history.xml | 20 +
   branches/release/libs/function/test/Jamfile.v2 | 3
   branches/release/libs/function/test/contains_test.cpp | 9
   branches/release/libs/function/test/function_n_test.cpp | 49 ++++
   6 files changed, 503 insertions(+), 201 deletions(-)

Modified: branches/release/boost/function/function_base.hpp
==============================================================================
--- branches/release/boost/function/function_base.hpp (original)
+++ branches/release/boost/function/function_base.hpp 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
@@ -18,8 +18,11 @@
 #include <typeinfo>
 #include <boost/config.hpp>
 #include <boost/assert.hpp>
+#include <boost/type_traits/is_const.hpp>
 #include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_volatile.hpp>
 #include <boost/type_traits/composite_traits.hpp>
+#include <boost/type_traits/ice.hpp>
 #include <boost/ref.hpp>
 #include <boost/mpl/if.hpp>
 #include <boost/detail/workaround.hpp>
@@ -30,6 +33,7 @@
 # include "boost/mpl/bool.hpp"
 #endif
 #include <boost/function_equal.hpp>
+#include <boost/function/function_fwd.hpp>
 
 #if defined(BOOST_MSVC)
 # pragma warning( push )
@@ -63,22 +67,7 @@
 # define BOOST_FUNCTION_TARGET_FIX(x)
 #endif // not MSVC
 
-#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
-// Work around a compiler bug.
-// boost::python::objects::function has to be seen by the compiler before the
-// boost::function class template.
-namespace boost { namespace python { namespace objects {
- class function;
-}}}
-#endif
-
-#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
- || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
- || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
-# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
-#endif
-
-#if !BOOST_WORKAROUND(__BORLANDC__, < 0x600)
+#if !BOOST_WORKAROUND(__BORLANDC__, < 0x5A0)
 # define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type) \
       typename ::boost::enable_if_c<(::boost::type_traits::ice_not< \
                             (::boost::is_integral<Functor>::value)>::value), \
@@ -92,22 +81,6 @@
                        Type>::type
 #endif
 
-#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
-namespace boost {
-
-template<typename Signature>
-class function;
-
-template<typename Signature>
-inline void swap(function<Signature>& f1,
- function<Signature>& f2)
-{
- f1.swap(f2);
-}
-
-} // end namespace boost
-#endif // have partial specialization
-
 namespace boost {
   namespace detail {
     namespace function {
@@ -122,11 +95,18 @@
       union function_buffer
       {
         // For pointers to function objects
- void* obj_ptr;
+ mutable void* obj_ptr;
 
         // For pointers to std::type_info objects
- // (get_functor_type_tag, check_functor_type_tag).
- const void* const_obj_ptr;
+ 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 function pointers of all kinds
         mutable void (*func_ptr)();
@@ -137,6 +117,14 @@
           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;
       };
@@ -168,6 +156,7 @@
       // 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
@@ -204,34 +193,45 @@
       struct reference_manager
       {
         static inline void
- get(const function_buffer& in_buffer, function_buffer& out_buffer,
- functor_manager_operation_type op)
+ manage(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op)
         {
           switch (op) {
           case clone_functor_tag:
- out_buffer.obj_ptr = in_buffer.obj_ptr;
+ 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;
 
           case destroy_functor_tag:
- out_buffer.obj_ptr = 0;
+ out_buffer.obj_ref.obj_ptr = 0;
             return;
 
           case check_functor_type_tag:
             {
- // DPG TBD: Since we're only storing a pointer, it's
- // possible that the user could ask for a base class or
- // derived class. Is that okay?
- const BOOST_FUNCTION_STD_NS::type_info& check_type =
- *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
- if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F)))
- out_buffer.obj_ptr = in_buffer.obj_ptr;
+ 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;
 
           case get_functor_type_tag:
- out_buffer.const_obj_ptr = &typeid(F);
+ 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;
           }
         }
@@ -277,15 +277,22 @@
         {
           if (op == clone_functor_tag)
             out_buffer.func_ptr = in_buffer.func_ptr;
- else if (op == destroy_functor_tag)
+ 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 /* op == check_functor_type_tag */ {
- const BOOST_FUNCTION_STD_NS::type_info& check_type =
- *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
+ 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;
           }
         }
 
@@ -294,20 +301,28 @@
         manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
                 functor_manager_operation_type op)
         {
- if (op == clone_functor_tag) {
+ 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 /* op == check_functor_type_tag */ {
- const BOOST_FUNCTION_STD_NS::type_info& check_type =
- *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
+ } 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;
           }
         }
       };
@@ -347,19 +362,26 @@
               (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 /* op == check_functor_type_tag */ {
- const BOOST_FUNCTION_STD_NS::type_info& check_type =
- *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
+ } 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;
           }
         }
 
@@ -374,6 +396,14 @@
                   mpl::bool_<(function_allows_small_object_optimization<functor_type>::value)>());
         }
 
+ // For member pointers, we use the small-object optimization buffer.
+ static inline void
+ manager(const function_buffer& in_buffer, function_buffer& out_buffer,
+ functor_manager_operation_type op, member_ptr_tag)
+ {
+ manager(in_buffer, out_buffer, op, mpl::true_());
+ }
+
       public:
         /* Dispatch to an appropriate manager based on whether we have a
            function pointer or a function object pointer. */
@@ -384,7 +414,9 @@
           typedef typename get_function_tag<functor_type>::type tag_type;
           switch (op) {
           case get_functor_type_tag:
- out_buffer.const_obj_ptr = &typeid(functor_type);
+ out_buffer.type.type = &typeid(functor_type);
+ out_buffer.type.const_qualified = false;
+ out_buffer.type.volatile_qualified = false;
             return;
 
           default:
@@ -439,6 +471,9 @@
             // Get back to the original pointer type
             functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
             out_buffer.obj_ptr = new_f;
+ } else if (op == 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_wrapper_type */
             functor_wrapper_type* victim =
@@ -447,13 +482,17 @@
             wrapper_allocator.destroy(victim);
             wrapper_allocator.deallocate(victim,1);
             out_buffer.obj_ptr = 0;
- } else /* op == check_functor_type_tag */ {
- const BOOST_FUNCTION_STD_NS::type_info& check_type =
- *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(out_buffer.const_obj_ptr);
+ } 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;
           }
         }
 
@@ -478,7 +517,9 @@
           typedef typename get_function_tag<functor_type>::type tag_type;
           switch (op) {
           case get_functor_type_tag:
- out_buffer.const_obj_ptr = &typeid(functor_type);
+ out_buffer.type.type = &typeid(functor_type);
+ out_buffer.type.const_qualified = false;
+ out_buffer.type.volatile_qualified = false;
             return;
 
           default:
@@ -556,7 +597,6 @@
        */
       struct vtable_base
       {
- vtable_base() : manager(0) { }
         void (*manager)(const function_buffer& in_buffer,
                         function_buffer& out_buffer,
                         functor_manager_operation_type op);
@@ -586,7 +626,7 @@
 
     detail::function::function_buffer type;
     vtable->manager(functor, type, detail::function::get_functor_type_tag);
- return *static_cast<const BOOST_FUNCTION_STD_NS::type_info*>(type.const_obj_ptr);
+ return *type.type.type;
   }
 
   template<typename Functor>
@@ -595,7 +635,9 @@
       if (!vtable) return 0;
 
       detail::function::function_buffer type_result;
- type_result.const_obj_ptr = &typeid(Functor);
+ type_result.type.type = &typeid(Functor);
+ type_result.type.const_qualified = is_const<Functor>::value;
+ type_result.type.volatile_qualified = is_volatile<Functor>::value;
       vtable->manager(functor, type_result,
                       detail::function::check_functor_type_tag);
       return static_cast<Functor*>(type_result.obj_ptr);
@@ -611,7 +653,9 @@
       if (!vtable) return 0;
 
       detail::function::function_buffer type_result;
- type_result.const_obj_ptr = &typeid(Functor);
+ type_result.type.type = &typeid(Functor);
+ type_result.type.const_qualified = true;
+ type_result.type.volatile_qualified = is_volatile<Functor>::value;
       vtable->manager(functor, type_result,
                       detail::function::check_functor_type_tag);
       // GCC 2.95.3 gets the CV qualifiers wrong here, so we

Added: branches/release/boost/function/function_fwd.hpp
==============================================================================
--- (empty file)
+++ branches/release/boost/function/function_fwd.hpp 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
@@ -0,0 +1,70 @@
+// Boost.Function library
+// Copyright (C) Douglas Gregor 2008
+//
+// Use, modification and distribution is subject to the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see http://www.boost.org
+#ifndef BOOST_FUNCTION_FWD_HPP
+#define BOOST_FUNCTION_FWD_HPP
+#include <boost/config.hpp>
+
+#if defined(__sgi) && defined(_COMPILER_VERSION) && _COMPILER_VERSION <= 730 && !defined(BOOST_STRICT_CONFIG)
+// Work around a compiler bug.
+// boost::python::objects::function has to be seen by the compiler before the
+// boost::function class template.
+namespace boost { namespace python { namespace objects {
+ class function;
+}}}
+#endif
+
+#if defined (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION) \
+ || defined(BOOST_BCB_PARTIAL_SPECIALIZATION_BUG) \
+ || !(BOOST_STRICT_CONFIG || !defined(__SUNPRO_CC) || __SUNPRO_CC > 0x540)
+# define BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX
+#endif
+
+namespace boost {
+ class bad_function_call;
+
+#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
+ // Preferred syntax
+ template<typename Signature> class function;
+
+ template<typename Signature>
+ inline void swap(function<Signature>& f1, function<Signature>& 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>
+ class function4;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5>
+ class function5;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6>
+ class function6;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7>
+ class function7;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8>
+ class function8;
+ template<typename R, typename T1, typename T2, typename T3, typename T4,
+ typename T5, typename T6, typename T7, typename T8, typename T9>
+ 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>
+ class function10;
+}
+
+#endif

Modified: branches/release/boost/function/function_template.hpp
==============================================================================
--- branches/release/boost/function/function_template.hpp (original)
+++ branches/release/boost/function/function_template.hpp 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
@@ -53,12 +53,20 @@
   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
@@ -180,6 +188,44 @@
         }
       };
 
+#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
@@ -243,11 +289,190 @@
>::type type;
       };
 
+#if BOOST_FUNCTION_NUM_ARGS > 0
+ /* Retrieve the appropriate invoker for a member pointer. */
+ template<
+ typename MemberPtr,
+ typename R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_PARMS
+ >
+ struct BOOST_FUNCTION_GET_MEMBER_INVOKER
+ {
+ typedef typename mpl::if_c<(is_void<R>::value),
+ BOOST_FUNCTION_VOID_MEMBER_INVOKER<
+ MemberPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >,
+ BOOST_FUNCTION_MEMBER_INVOKER<
+ MemberPtr,
+ R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS
+ >
+ >::type type;
+ };
+#endif
+
+ /* Given the tag returned by get_function_tag, retrieve the
+ actual invoker that will be used for the given function
+ object.
+
+ Each specialization contains an "apply" nested class template
+ that accepts the function object, return type, function
+ argument types, and allocator. The resulting "apply" class
+ contains two typedefs, "invoker_type" and "manager_type",
+ which correspond to the invoker and manager types. */
+ template<typename Tag>
+ struct BOOST_FUNCTION_GET_INVOKER { };
+
+ /* Retrieve the invoker for a function pointer. */
+ template<>
+ struct BOOST_FUNCTION_GET_INVOKER<function_ptr_tag>
+ {
+ template<typename FunctionPtr,
+ typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
+ 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.
+ * 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 : vtable_base
+ struct BOOST_FUNCTION_VTABLE
       {
 #ifndef BOOST_NO_VOID_RETURNS
         typedef R result_type;
@@ -260,17 +485,6 @@
                                             BOOST_FUNCTION_TEMPLATE_ARGS);
 
         template<typename F>
- BOOST_FUNCTION_VTABLE(F f) : vtable_base(), invoker(0)
- {
- init(f);
- }
- template<typename F,typename Allocator>
- BOOST_FUNCTION_VTABLE(F f, Allocator) : vtable_base(), invoker(0)
- {
- init_a<Allocator>(f);
- }
-
- template<typename F>
         bool assign_to(F f, function_buffer& functor)
         {
           typedef typename get_function_tag<F>::type tag;
@@ -285,53 +499,13 @@
 
         void clear(function_buffer& functor)
         {
- if (manager)
- manager(functor, functor, destroy_functor_tag);
+ if (base.manager)
+ base.manager(functor, functor, destroy_functor_tag);
         }
 
       private:
- template<typename F>
- void init(F f)
- {
- typedef typename get_function_tag<F>::type tag;
- init(f, tag());
- }
- template<typename Allocator,typename F>
- void init_a(F f)
- {
- typedef typename get_function_tag<F>::type tag;
- init_a<Allocator>(f, tag());
- }
-
         // Function pointers
         template<typename FunctionPtr>
- void init(FunctionPtr /*f*/, function_ptr_tag)
- {
- typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
- FunctionPtr,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- actual_invoker_type;
-
- invoker = &actual_invoker_type::invoke;
- manager = &functor_manager<FunctionPtr>::manage;
- }
- template<typename Allocator,typename FunctionPtr>
- void init_a(FunctionPtr f, function_ptr_tag)
- {
- typedef typename BOOST_FUNCTION_GET_FUNCTION_INVOKER<
- FunctionPtr,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- actual_invoker_type;
-
- invoker = &actual_invoker_type::invoke;
- manager = &functor_manager_a<FunctionPtr, Allocator>::manage;
- }
-
- template<typename FunctionPtr>
         bool
         assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag)
         {
@@ -355,23 +529,6 @@
         // Member pointers
 #if BOOST_FUNCTION_NUM_ARGS > 0
         template<typename MemberPtr>
- void init(MemberPtr f, member_ptr_tag)
- {
- // DPG TBD: Add explicit support for member function
- // objects, so we invoke through mem_fn() but we retain the
- // right target_type() values.
- this->init(mem_fn(f));
- }
- template<typename Allocator,typename MemberPtr>
- void init_a(MemberPtr f, member_ptr_tag)
- {
- // DPG TBD: Add explicit support for member function
- // objects, so we invoke through mem_fn() but we retain the
- // right target_type() values.
- this->init_a<Allocator>(mem_fn(f));
- }
-
- template<typename MemberPtr>
         bool assign_to(MemberPtr f, function_buffer& functor, member_ptr_tag)
         {
           // DPG TBD: Add explicit support for member function
@@ -400,33 +557,6 @@
 #endif // BOOST_FUNCTION_NUM_ARGS > 0
 
         // Function objects
- template<typename FunctionObj>
- void init(FunctionObj /*f*/, function_obj_tag)
- {
- typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
- FunctionObj,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- actual_invoker_type;
-
- invoker = &actual_invoker_type::invoke;
- manager = &functor_manager<FunctionObj>::manage;
- }
- template<typename Allocator,typename FunctionObj>
- void init_a(FunctionObj /*f*/, function_obj_tag)
- {
- typedef typename BOOST_FUNCTION_GET_FUNCTION_OBJ_INVOKER<
- FunctionObj,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- actual_invoker_type;
-
- invoker = &actual_invoker_type::invoke;
- manager = &functor_manager_a<FunctionObj, Allocator>::manage;
- }
-
         // Assign to a function object using the small object optimization
         template<typename FunctionObj>
         void
@@ -490,37 +620,14 @@
 
         // Reference to a function object
         template<typename FunctionObj>
- void
- init(const reference_wrapper<FunctionObj>& /*f*/, function_obj_ref_tag)
- {
- typedef typename BOOST_FUNCTION_GET_FUNCTION_REF_INVOKER<
- FunctionObj,
- R BOOST_FUNCTION_COMMA
- BOOST_FUNCTION_TEMPLATE_ARGS
- >::type
- actual_invoker_type;
-
- invoker = &actual_invoker_type::invoke;
- manager = &reference_manager<FunctionObj>::get;
- }
- template<typename Allocator,typename FunctionObj>
- void
- init_a(const reference_wrapper<FunctionObj>& f, function_obj_ref_tag)
- {
- init(f,function_obj_ref_tag());
- }
-
- template<typename FunctionObj>
         bool
         assign_to(const reference_wrapper<FunctionObj>& f,
                   function_buffer& functor, function_obj_ref_tag)
         {
           if (!boost::detail::function::has_empty_target(f.get_pointer())) {
- // DPG TBD: We might need to detect constness of
- // FunctionObj to assign into obj_ptr or const_obj_ptr to
- // be truly legit, but no platform in existence makes
- // const void* different from void*.
- functor.const_obj_ptr = f.get_pointer();
+ 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;
           } else {
             return false;
@@ -535,6 +642,7 @@
         }
 
       public:
+ vtable_base base;
         invoker_type invoker;
       };
     } // end namespace function
@@ -729,16 +837,17 @@
       if (&other == this)
         return;
 
- BOOST_FUNCTION_FUNCTION tmp = *this;
- *this = other;
- other = tmp;
+ 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) {
- static_cast<vtable_type*>(vtable)->clear(this->functor);
+ reinterpret_cast<vtable_type*>(vtable)->clear(this->functor);
         vtable = 0;
       }
     }
@@ -775,17 +884,82 @@
     template<typename Functor>
     void assign_to(Functor f)
     {
- static vtable_type stored_vtable(f);
- if (stored_vtable.assign_to(f, functor)) vtable = &stored_vtable;
+ using detail::function::vtable_base;
+
+ typedef typename detail::function::get_function_tag<Functor>::type tag;
+ typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
+ typedef typename get_invoker::
+ template apply<Functor, R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS>
+ 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(f, functor)) vtable = &stored_vtable.base;
       else vtable = 0;
     }
+
     template<typename Functor,typename Allocator>
     void assign_to_a(Functor f,Allocator a)
     {
- static vtable_type stored_vtable(f,a);
- if (stored_vtable.assign_to_a(f, functor, a)) vtable = &stored_vtable;
+ using detail::function::vtable_base;
+
+ typedef typename detail::function::get_function_tag<Functor>::type tag;
+ typedef detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
+ typedef typename get_invoker::
+ template apply_a<Functor, R BOOST_FUNCTION_COMMA
+ BOOST_FUNCTION_TEMPLATE_ARGS,
+ Allocator>
+ handler_type;
+
+ typedef typename handler_type::invoker_type invoker_type;
+ typedef typename handler_type::manager_type manager_type;
+
+ // 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)) vtable = &stored_vtable.base;
       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;
+
+#if !defined(BOOST_NO_EXCEPTIONS)
+ try {
+#endif
+ if (!f.empty()) {
+ this->vtable = f.vtable;
+ f.vtable->manager(f.functor, this->functor,
+ boost::detail::function::move_functor_tag);
+ f.vtable = 0;
+#if !defined(BOOST_NO_EXCEPTIONS)
+ } else {
+ clear();
+ }
+ } catch (...) {
+ vtable = 0;
+ throw;
+ }
+#endif
+ }
   };
 
   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS>
@@ -811,7 +985,7 @@
     if (this->empty())
       boost::throw_exception(bad_function_call());
 
- return static_cast<vtable_type*>(vtable)->invoker
+ return reinterpret_cast<const vtable_type*>(vtable)->invoker
              (this->functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS);
   }
 #endif
@@ -938,10 +1112,13 @@
 #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

Added: branches/release/boost/function/function_typeof.hpp
==============================================================================
--- (empty file)
+++ branches/release/boost/function/function_typeof.hpp 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
@@ -0,0 +1,45 @@
+// Boost.Function library - Typeof support
+// Copyright (C) Douglas Gregor 2008
+//
+// Use, modification and distribution is subject to the Boost
+// Software License, Version 1.0. (See accompanying file
+// LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+// For more information, see http://www.boost.org
+#ifndef BOOST_FUNCTION_TYPEOF_HPP
+#define BOOST_FUNCTION_TYPEOF_HPP
+#include <boost/function/function_fwd.hpp>
+#include <boost/typeof/typeof.hpp>
+
+#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
+
+BOOST_TYPEOF_REGISTER_TYPE(boost::bad_function_call)
+
+#if !defined(BOOST_FUNCTION_NO_FUNCTION_TYPE_SYNTAX)
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function, (typename))
+#endif
+
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function0, (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function1, (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function2, (typename)(typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function3,
+ (typename)(typename)(typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function4,
+ (typename)(typename)(typename)(typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function5,
+ (typename)(typename)(typename)(typename)(typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function6,
+ (typename)(typename)(typename)(typename)(typename)(typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function7,
+ (typename)(typename)(typename)(typename)(typename)(typename)(typename)
+ (typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function8,
+ (typename)(typename)(typename)(typename)(typename)(typename)(typename)
+ (typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function9,
+ (typename)(typename)(typename)(typename)(typename)(typename)(typename)
+ (typename)(typename)(typename))
+BOOST_TYPEOF_REGISTER_TEMPLATE(boost::function10,
+ (typename)(typename)(typename)(typename)(typename)(typename)(typename)
+ (typename)(typename)(typename)(typename))
+#endif

Modified: branches/release/libs/function/doc/history.xml
==============================================================================
--- branches/release/libs/function/doc/history.xml (original)
+++ branches/release/libs/function/doc/history.xml 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
@@ -13,6 +13,26 @@
 
 <itemizedlist spacing="compact">
 
+ <listitem><para><bold>Version 1.37.0</bold>: </para>
+ <itemizedlist spacing="compact">
+ <listitem><para>Improved the performance of Boost.Function's
+ swap() operation for large function objects. Original patch
+ contributed by Niels Dekker.</para></listitem>
+
+ <listitem><para>Added a new header &lt;boost/function/function_typeof.hpp&gt; that provides support for using the Boost.Typeof library on Boost.Function objects.</para></listitem>
+
+ <listitem><para>Added a new header &lt;boost/function/function_fwd.hpp&gt; that provides support for using the Boost.Typeof library on Boost.Function objects.</para></listitem>
+
+ <listitem><para>The <methodname alt="boost::function::target">target</methodname>()
+ function now respects the cv-qualifiers of function objects
+ stored by reference
+ (using <classname>boost::reference_wrapper</classname>), such
+ that a reference to a <code>const</code> function object cannot
+ be accessed as a reference to a non-<code>const</code> function
+ object.</para></listitem>
+ </itemizedlist>
+ </listitem>
+
   <listitem><para><bold>Version 1.36.0</bold>: </para>
     <itemizedlist spacing="compact">
       <listitem><para>Boost.Function now implements allocator support

Modified: branches/release/libs/function/test/Jamfile.v2
==============================================================================
--- branches/release/libs/function/test/Jamfile.v2 (original)
+++ branches/release/libs/function/test/Jamfile.v2 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
@@ -58,6 +58,9 @@
    
   [ run libs/function/test/contains2_test.cpp : : : : ]
    
+ [ run libs/function/test/nothrow_swap.cpp : : : : ]
+
+ [ compile libs/function/test/function_typeof_test.cpp ]
  ;
 }
       

Modified: branches/release/libs/function/test/contains_test.cpp
==============================================================================
--- branches/release/libs/function/test/contains_test.cpp (original)
+++ branches/release/libs/function/test/contains_test.cpp 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
@@ -88,6 +88,15 @@
   BOOST_CHECK(!f.target<int (*)()>());
   BOOST_CHECK(f.target<Seventeen>());
   BOOST_CHECK(f.target<Seventeen>() == &this_seventeen);
+
+ const Seventeen const_seventeen = this_seventeen;
+ f = boost::ref(const_seventeen);
+ BOOST_CHECK(!f.target<int (*)()>());
+ BOOST_CHECK(f.target<const Seventeen>());
+ BOOST_CHECK(f.target<const Seventeen>() == &const_seventeen);
+ BOOST_CHECK(f.target<const volatile Seventeen>());
+ BOOST_CHECK(!f.target<Seventeen>());
+ BOOST_CHECK(!f.target<volatile Seventeen>());
 }
 
 static void equal_test()

Modified: branches/release/libs/function/test/function_n_test.cpp
==============================================================================
--- branches/release/libs/function/test/function_n_test.cpp (original)
+++ branches/release/libs/function/test/function_n_test.cpp 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
@@ -636,6 +636,54 @@
   }
 }
 
+static unsigned construction_count = 0;
+static unsigned destruction_count = 0;
+
+struct MySmallFunctor {
+ MySmallFunctor() { ++construction_count; }
+ MySmallFunctor(const MySmallFunctor &) { ++construction_count; }
+ ~MySmallFunctor() { ++destruction_count; }
+ int operator()() { return 0; }
+ };
+
+struct MyLargeFunctor {
+ MyLargeFunctor() { ++construction_count; }
+ MyLargeFunctor(const MyLargeFunctor &) { ++construction_count; }
+ ~MyLargeFunctor() { ++destruction_count; }
+ int operator()() { return 0; }
+
+ float data[128];
+ };
+
+void test_construct_destroy_count()
+{
+ {
+ boost::function0<int> f;
+ boost::function0<int> g;
+ f = MySmallFunctor();
+ g = MySmallFunctor();
+ f.swap(g);
+ }
+
+ // MySmallFunctor objects should be constructed as many times as
+ // they are destroyed.
+ BOOST_CHECK(construction_count == destruction_count);
+
+ construction_count = 0;
+ destruction_count = 0;
+ {
+ boost::function0<int> f;
+ boost::function0<int> g;
+ f = MyLargeFunctor();
+ g = MyLargeFunctor();
+ f.swap(g);
+ }
+
+ // MyLargeFunctor objects should be constructed as many times as
+ // they are destroyed.
+ BOOST_CHECK(construction_count == destruction_count);
+}
+
 int test_main(int, char* [])
 {
   test_zero_args();
@@ -644,5 +692,6 @@
   test_emptiness();
   test_member_functions();
   test_ref();
+ test_construct_destroy_count();
   return 0;
 }

Added: branches/release/libs/function/test/function_typeof_test.cpp
==============================================================================
--- (empty file)
+++ branches/release/libs/function/test/function_typeof_test.cpp 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
@@ -0,0 +1,18 @@
+// Boost.Function library
+
+// Copyright Douglas Gregor 2008. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+#include <boost/function/function_typeof.hpp>
+#include <boost/function.hpp>
+#include <boost/typeof/typeof.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/static_assert.hpp>
+
+void f(boost::function0<void> f, boost::function0<void> g)
+{
+ BOOST_STATIC_ASSERT((boost::is_same<boost::function0<void>, BOOST_TYPEOF(f = g)>::value));
+}

Added: branches/release/libs/function/test/nothrow_swap.cpp
==============================================================================
--- (empty file)
+++ branches/release/libs/function/test/nothrow_swap.cpp 2008-10-16 09:21:50 EDT (Thu, 16 Oct 2008)
@@ -0,0 +1,60 @@
+// Boost.Function library
+
+// Copyright Douglas Gregor 2008. Use, modification and
+// distribution is subject to the Boost Software License, Version
+// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+// For more information, see http://www.boost.org
+
+#include <boost/test/minimal.hpp>
+#include <boost/function.hpp>
+
+struct tried_to_copy { };
+
+struct MaybeThrowOnCopy {
+ MaybeThrowOnCopy(int value = 0) : value(value) { }
+
+ MaybeThrowOnCopy(const MaybeThrowOnCopy& other) : value(other.value) {
+ if (throwOnCopy)
+ throw tried_to_copy();
+ }
+
+ MaybeThrowOnCopy& operator=(const MaybeThrowOnCopy& other) {
+ if (throwOnCopy)
+ throw tried_to_copy();
+ value = other.value;
+ return *this;
+ }
+
+ int operator()() { return value; }
+
+ int value;
+
+ // Make sure that this function object doesn't trigger the
+ // small-object optimization in Function.
+ float padding[100];
+
+ static bool throwOnCopy;
+};
+
+bool MaybeThrowOnCopy::throwOnCopy = false;
+
+int test_main(int, char* [])
+{
+ boost::function0<int> f;
+ boost::function0<int> g;
+
+ MaybeThrowOnCopy::throwOnCopy = false;
+ f = MaybeThrowOnCopy(1);
+ g = MaybeThrowOnCopy(2);
+ BOOST_CHECK(f() == 1);
+ BOOST_CHECK(g() == 2);
+
+ MaybeThrowOnCopy::throwOnCopy = true;
+ f.swap(g);
+ BOOST_CHECK(f() == 2);
+ BOOST_CHECK(g() == 1);
+
+ return 0;
+}


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