$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r66407 - in sandbox/function/boost/function: . detail
From: dsaritz_at_[hidden]
Date: 2010-11-05 17:32:26
Author: psiha
Date: 2010-11-05 17:32:01 EDT (Fri, 05 Nov 2010)
New Revision: 66407
URL: http://svn.boost.org/trac/boost/changeset/66407
Log:
Compeletly refactored plain function pointer/reference assignment code to
 - try and finally solve the 'ampersandless' syntax problems for all cases
 - fix null function pointer assignment
 - optimize direct plain function assignemnt (make the compiler see the pointer is not null).
Text files modified: 
   sandbox/function/boost/function/detail/platform_specifics.hpp |     4                                         
   sandbox/function/boost/function/function_base.hpp             |    65 +++++----                               
   sandbox/function/boost/function/function_template.hpp         |   265 +++++++++++++++++++-------------------- 
   3 files changed, 170 insertions(+), 164 deletions(-)
Modified: sandbox/function/boost/function/detail/platform_specifics.hpp
==============================================================================
--- sandbox/function/boost/function/detail/platform_specifics.hpp	(original)
+++ sandbox/function/boost/function/detail/platform_specifics.hpp	2010-11-05 17:32:01 EDT (Fri, 05 Nov 2010)
@@ -58,11 +58,15 @@
     #define BF_UNREACHABLE_CODE    BOOST_ASSERT( !"This code should not be reached." ); __assume( false );
     #define BF_ASSUME( condition ) BOOST_ASSERT( condition ); __assume( condition )
 
+    #define BF_TAKES_FUNCTION_REFERENCES
+
     #define BF_GNU_SPECIFIC(  expression )
     #define BF_MSVC_SPECIFIC( expression ) expression
 
 #elif defined( __clang__ ) || defined( __GNUC__ )
 
+    #define BF_TAKES_FUNCTION_REFERENCES
+
     #define BF_NOVTABLE
     #define BF_NOTHROW                  __attribute__(( nothrow ))
     #define BF_NOALIAS
Modified: sandbox/function/boost/function/function_base.hpp
==============================================================================
--- sandbox/function/boost/function/function_base.hpp	(original)
+++ sandbox/function/boost/function/function_base.hpp	2010-11-05 17:32:01 EDT (Fri, 05 Nov 2010)
@@ -119,20 +119,23 @@
 #  define BOOST_FUNCTION_TARGET_FIX(x)
 #endif // not MSVC
 
-#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), \
+#ifndef BOOST_NO_SFINAE
+    #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), \
+                               Type>::type
+    #else
+    // BCC doesn't recognize this depends on a template argument and complains
+    // about the use of 'typename'
+    #  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)       \
+          ::boost::enable_if_c<(::boost::type_traits::ice_not<          \
+                       (::boost::is_integral<Functor>::value)>::value), \
                            Type>::type
-#else
-// BCC doesn't recognize this depends on a template argument and complains
-// about the use of 'typename'
-#  define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL(Functor,Type)       \
-      ::boost::enable_if_c<(::boost::type_traits::ice_not<          \
-                   (::boost::is_integral<Functor>::value)>::value), \
-                       Type>::type
-#endif
-
+    #endif
+#else // BOOST_NO_SFINAE
+    #define BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL( Functor, Type ) Type
+#endif // BOOST_NO_SFINAE
 
 #if defined( __IBMCPP__ ) || defined( __clang__ ) || ( defined( __GNUC__ ) && ( ( ( __GNUC__ * 10 ) + __GNUC_MINOR__ ) < 45 ) )
     #define BOOST_FUNCTION_CLANG_AND_OLD_GCC_BROKEN_STATIC_ASSERT BOOST_ASSERT
@@ -413,6 +416,9 @@
       {
         typedef typename mpl::if_c<(is_pointer<F>::value ||
                                    is_function<F>::value ||
+                                   #ifdef BOOST_NO_SFINAE
+                                     is_integral<F>::value || // to interpret NULL as function pointer...
+                                   #endif // BOOST_NO_SFINAE
                                    is_msvc_exception_specified_function_pointer<F>::value),
                                    function_ptr_tag,
                                    function_obj_tag>::type ptr_or_obj_tag;
@@ -1648,15 +1654,15 @@
   namespace function {
 
     template <typename T>
-    BF_FORCEINLINE bool has_empty_target_aux( T const * const funcPtr, function_ptr_tag )
+    BF_FORCEINLINE bool has_empty_target( T * const funcPtr, function_ptr_tag )
     {
         return funcPtr == 0;
     }
 
     template <typename T>
-    BF_FORCEINLINE bool has_empty_target_aux( T const * const funcPtr, member_ptr_tag )
+    BF_FORCEINLINE bool has_empty_target_aux( T * const funcPtr, member_ptr_tag )
     {
-        return has_empty_target_aux<T>( funcPtr, function_ptr_tag() );
+        return has_empty_target<T>( funcPtr, function_ptr_tag() );
     }
 
     BF_FORCEINLINE bool has_empty_target_aux( function_base const * const f, function_obj_tag )
@@ -1675,30 +1681,26 @@
         return false;
     }
 
+    template <typename T>
+    BF_FORCEINLINE bool has_empty_target( T const & f, function_obj_tag )
+    {
+        return has_empty_target_aux( boost::addressof( f ), function_obj_tag() );
+    }
+
     // Implementation note:
     //   This has to be after the void const * overload because of non-lazy
     // compilers (e.g. GCC 4.2.1).
     //                                        (28.10.2010.) (Domagoj Saric)
     template <class FunctionObj>
-    BF_FORCEINLINE bool has_empty_target_aux( reference_wrapper<FunctionObj> const * const f, function_obj_ref_tag )
+    BF_FORCEINLINE bool has_empty_target( reference_wrapper<FunctionObj> const & f, function_obj_ref_tag )
     {
         // Implementation note:
         //   We save/assign a reference to a boost::function even if it is empty
         // and let the referenced function handle a possible empty invocation.
         //                                    (28.10.2010.) (Domagoj Saric)
-        BF_ASSUME( f                != 0 );
-        BF_ASSUME( f->get_pointer() != 0 );
         return is_base_of<function_base, FunctionObj>::value
-            ? ( f == 0 )
-            : has_empty_target_aux( f->get_pointer(), function_obj_tag() );
-    }
-
-
-    template <typename T>
-    BF_FORCEINLINE bool has_empty_target( T const * const f )
-    {
-        typedef typename get_function_tag<T>::type tag;
-        return has_empty_target_aux( f, tag() );
+            ? false
+            : has_empty_target( f.get(), function_obj_tag() );
     }
 
 
@@ -1738,7 +1740,8 @@
 {
     using namespace detail::function;
 
-    if ( has_empty_target( boost::addressof( f ) ) )
+    typedef typename get_function_tag<FunctionObj>::type tag;
+    if ( has_empty_target( f, tag() ) )
         this->clear<direct, EmptyHandler>( empty_handler_vtable );
     else
     if ( direct )
@@ -1788,7 +1791,7 @@
 
 } // end namespace boost
 
-#undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
+//...zzz...required in function_template.hpp #undef BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL
 #undef BOOST_FUNCTION_COMPARE_TYPE_ID
 //...zzz...required in function_template.hpp #undef BOOST_FUNCTION_CLANG_AND_OLD_GCC_BROKEN_STATIC_ASSERT
 #undef BF_VT_REF
Modified: sandbox/function/boost/function/function_template.hpp
==============================================================================
--- sandbox/function/boost/function/function_template.hpp	(original)
+++ sandbox/function/boost/function/function_template.hpp	2010-11-05 17:32:01 EDT (Fri, 05 Nov 2010)
@@ -70,6 +70,23 @@
 #  define BOOST_FUNCTION_RETURN(X) X; return BOOST_FUNCTION_VOID_RETURN_TYPE ()
 #endif
 
+#ifndef BOOST_NO_SFINAE
+    #define BOOST_FUNCTION_NULL_POINTER_ASSIGNMENT( ReturnType )            \
+    ReturnType & operator=( detail::function::useless_clear_type const * )  \
+    {                                                                       \
+        this->clear();                                                      \
+        return *this;                                                       \
+    }
+#else // BOOST_NO_SFINAE
+    #define BOOST_FUNCTION_NULL_POINTER_ASSIGNMENT( ReturnType )            \
+    ReturnType & operator=( int const zero )                                \
+    {                                                                       \
+        BOOST_ASSERT( zero == 0 );                                          \
+        this->clear();                                                      \
+        return *this;                                                       \
+    }
+#endif // BOOST_NO_SFINAE
+
 namespace boost {
   namespace detail {
     namespace function {
@@ -178,20 +195,16 @@
     BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS);
 
     // add signature for boost::lambda
-    template<typename Args>
-    struct sig
-    {
-      typedef result_type type;
-    };
+    template <typename Args> struct sig { typedef result_type type; };
 
-#if BOOST_FUNCTION_NUM_ARGS == 1
+#if   BOOST_FUNCTION_NUM_ARGS == 1
     typedef T0 argument_type;
 #elif BOOST_FUNCTION_NUM_ARGS == 2
     typedef T0 first_argument_type;
     typedef T1 second_argument_type;
 #endif
 
-    BOOST_STATIC_CONSTANT(int, arity = BOOST_FUNCTION_NUM_ARGS);
+    BOOST_STATIC_CONSTANT( int, arity = BOOST_FUNCTION_NUM_ARGS );
     BOOST_FUNCTION_ARG_TYPES
 
     typedef BOOST_FUNCTION_FUNCTION self_type;
@@ -237,8 +250,6 @@
 
     typedef detail::function::vtable vtable_type;
 
-    struct clear_type {};
-
   public: // Public function interface.
 
     BOOST_FUNCTION_FUNCTION() : function_base( empty_handler_vtable(), base_empty_handler() )
@@ -256,69 +267,40 @@
         #endif // BOOST_MSVC
     }
 
-
-    // MSVC chokes if the following two constructors are collapsed into
-    // one with a default parameter.
     template <typename Functor>
-    BOOST_FUNCTION_FUNCTION
-    (
-        Functor const & f
-        #ifndef BOOST_NO_SFINAE
-            ,typename enable_if_c<
-            (boost::type_traits::ice_not<
-                (is_integral<Functor>::value)>::value),
-                        int>::type = 0
-        #endif // BOOST_NO_SFINAE
-    )
-        : function_base( no_eh_state_construction_trick( f ) )
-    {}
+    BOOST_FUNCTION_FUNCTION( Functor const & f,                    BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL( Functor, int ) = 0 )
+        : function_base( no_eh_state_construction_trick( f ) ) {}
 
     template <typename Functor, typename Allocator>
-    BOOST_FUNCTION_FUNCTION
-    (
-        Functor const & f,
-        Allocator const a
+    BOOST_FUNCTION_FUNCTION( Functor const & f, Allocator const a, BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL( Functor, int ) = 0 )
+        : function_base( no_eh_state_construction_trick( f, a ) ) {}
+
+    #ifdef BF_TAKES_FUNCTION_REFERENCES
+        BOOST_FUNCTION_FUNCTION( signature_type & plain_function_reference )
+            : function_base( no_eh_state_construction_trick( plain_function_reference ) ) { BF_ASSUME( &plain_function_reference ); }
         #ifndef BOOST_NO_SFINAE
-            ,typename enable_if_c<
-            (boost::type_traits::ice_not<
-                (is_integral<Functor>::value)>::value),
-                        int>::type = 0
+            BOOST_FUNCTION_FUNCTION( detail::function::useless_clear_type const * )
+                : function_base( empty_handler_vtable(), base_empty_handler() ) {}
+        #else
+            BOOST_FUNCTION_FUNCTION( int const zero )
+                : function_base( empty_handler_vtable(), base_empty_handler() ) { BOOST_ASSERT( zero == 0 ); }
         #endif // BOOST_NO_SFINAE
-    )
-        : function_base( no_eh_state_construction_trick( f, a ) )
-    {}
-
-
-#ifndef BOOST_NO_SFINAE
-    BOOST_FUNCTION_FUNCTION(clear_type*) : function_base( empty_handler_vtable(), base_empty_handler() ) { }
-#else
-    BOOST_FUNCTION_FUNCTION(int zero) : function_base( empty_handler_vtable(), base_empty_handler() )
-    {
-      BOOST_ASSERT(zero == 0);
-    }
-#endif
+    #else // BF_TAKES_FUNCTION_REFERENCES
+        BOOST_FUNCTION_FUNCTION( signature_type * const plain_function_pointer )
+            : function_base( no_eh_state_construction_trick( plain_function_pointer ) ) {}
+    #endif // BF_TAKES_FUNCTION_REFERENCES
 
     BOOST_FUNCTION_FUNCTION( BOOST_FUNCTION_FUNCTION const & f )
-        : function_base( static_cast<function_base const &>( f ) )
-    {}
+        : function_base( static_cast<function_base const &>( f ) ) {}
 
     /// Clear out a target (replace it with an empty handler), if there is one.
-    void clear()
-    {
-        function_base::clear<false, base_empty_handler>( empty_handler_vtable() );
-    }
+    void clear() { function_base::clear<false, base_empty_handler>( empty_handler_vtable() ); }
 
-    template<typename FunctionObj>
-    void assign( FunctionObj const & f )
-    {
-        this->do_assign<false, FunctionObj>( f );
-    }
+    template <typename FunctionObj>
+    void assign( FunctionObj const & f                    ) { this->do_assign<false, FunctionObj>( f    ); }
 
     template <typename FunctionObj, typename Allocator>
-    void assign( FunctionObj const & f, Allocator const a )
-    {
-        this->do_assign<false, FunctionObj>( f, a );
-    }
+    void assign( FunctionObj const & f, Allocator const a ) { this->do_assign<false, FunctionObj>( f, a ); }
 
     template <signature_type * f>
     void assign()
@@ -376,35 +358,29 @@
     }
 
     template <typename Functor>
-#ifndef BOOST_NO_SFINAE
-    typename enable_if_c<
-               (boost::type_traits::ice_not<
-                 (is_integral<Functor>::value)>::value),
-               BOOST_FUNCTION_FUNCTION&>::type
-#else
-    BOOST_FUNCTION_FUNCTION &
-#endif
+    BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL( Functor, BOOST_FUNCTION_FUNCTION & )
     operator=( Functor const & f )
     {
       this->assign( f );
       return *this;
     }
 
+    #ifdef BF_TAKES_FUNCTION_REFERENCES
+        BOOST_FUNCTION_FUNCTION & operator=( signature_type & plain_function_reference )
+        {
+            BF_ASSUME( &plain_function_reference );
+            this->assign( plain_function_reference );
+            return *this;
+        }
 
-#ifndef BOOST_NO_SFINAE
-    BOOST_FUNCTION_FUNCTION & operator=(clear_type*)
-    {
-      this->clear();
-      return *this;
-    }
-#else
-    BOOST_FUNCTION_FUNCTION & operator=(int zero)
-    {
-      BOOST_ASSERT(zero == 0);
-      this->clear();
-      return *this;
-    }
-#endif
+        BOOST_FUNCTION_NULL_POINTER_ASSIGNMENT( BOOST_FUNCTION_FUNCTION )
+    #else // BF_TAKES_FUNCTION_REFERENCES
+        BOOST_FUNCTION_FUNCTION & operator=( signature_type * const plain_function_pointer )
+        {
+            this->assign( plain_function_pointer );
+            return *this;
+        }
+    #endif // BF_TAKES_FUNCTION_REFERENCES
 
     void swap( BOOST_FUNCTION_FUNCTION & other )
     {
@@ -636,7 +612,36 @@
                 typename remove_pointer<FunctionObj>::type
             >::type
         >::type non_const_function_pointer_t;
-        do_assign<direct, non_const_function_pointer_t, non_const_function_pointer_t>( f, f, a );
+
+        // Implementation note:
+        //   Single place to handle int-assignment for non SFINAE enabled
+        // compilers.
+        //                                    (05.11.2010.) (Domagoj Saric)
+        #ifdef BOOST_NO_SFINAE
+            typedef typename mpl::if_
+            <
+                is_integral<FunctionObj>,
+                signature_type *,
+                non_const_function_pointer_t
+            >::type correct_type_t;
+
+            if ( is_integral<FunctionObj>::value )
+            {
+                BOOST_ASSERT( reinterpret_cast<int const &>( f ) == 0 );
+                function_base::clear<direct, base_empty_handler>( empty_handler_vtable() );
+            }
+            else
+            {
+                // Implementation note:
+                //   Ugh...(exactly) this seems to work with the 'ampersandless'
+                // syntax.
+                //                            (05.11.2010.) (Domagoj Saric)
+                do_assign<direct, correct_type_t, correct_type_t>( reinterpret_cast<correct_type_t>( f ), reinterpret_cast<correct_type_t>( f ), a );
+            }
+        #else
+            typedef non_const_function_pointer_t correct_type_t;
+            do_assign<direct, non_const_function_pointer_t, non_const_function_pointer_t>( f, f, a );
+        #endif
     }
 
     template <bool direct, typename ActualFunctor, typename StoredFunctor, typename ActualFunctorAllocator>
@@ -725,6 +730,16 @@
         do_assign<true>( f, detail::function::fallocator<FunctionObj>() );
         return function_base::get_vtable();
     }
+
+    #ifdef BF_TAKES_FUNCTION_REFERENCES
+        detail::function::vtable const & no_eh_state_construction_trick( signature_type & plain_function_reference )
+        {
+            BF_ASSUME( &plain_function_reference );
+            detail::function::debug_clear( *this );
+            do_assign<true>( plain_function_reference );
+            return function_base::get_vtable();
+        }
+    #endif // BF_TAKES_FUNCTION_REFERENCES
   };
 
   template<typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, class PolicyList>
@@ -778,77 +793,59 @@
   function() {}
 
   template <typename Functor>
-  function
-  (
-    Functor const & f
-    #ifndef BOOST_NO_SFINAE
-        ,typename enable_if_c<
-                        (boost::type_traits::ice_not<
-                        (is_integral<Functor>::value)>::value),
-                    int>::type = 0
-    #endif
-  )
-    :
-    base_type( f )
-  {}
+  function( Functor const & f,                    BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL( Functor, int ) = 0 ) : base_type( f    ) {}
 
   template <typename Functor, typename Allocator>
-  function
-  (
-    Functor   const & f,
-    Allocator const   a
-    #ifndef BOOST_NO_SFINAE
-        ,typename enable_if_c<
-                        (boost::type_traits::ice_not<
-                        (is_integral<Functor>::value)>::value),
-                    int>::type = 0
-    #endif
-  )
-    :
-    base_type( f, a )
-  {}
+  function( Functor const & f, Allocator const a, BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL( Functor, int ) = 0 ) : base_type( f, a ) {}
 
-#ifndef BOOST_NO_SFINAE
-  function(clear_type*) : base_type() {}
-#endif
+  #ifdef BF_TAKES_FUNCTION_REFERENCES
+    function( typename base_type::signature_type &       plain_function_reference ) : base_type( plain_function_reference ) {}
+    #ifndef BOOST_NO_SFINAE
+        function( detail::function::useless_clear_type const * ) : base_type() {}
+    #endif // BOOST_NO_SFINAE
+  #else // BF_TAKES_FUNCTION_REFERENCES
+    function( typename base_type::signature_type * const plain_function_pointer   ) : base_type( plain_function_pointer   ) {}
+  #endif // BF_TAKES_FUNCTION_REFERENCES
 
-  function(const self_type& f) : base_type(static_cast<const base_type&>(f)){}
+  function( self_type const & f ) : base_type( static_cast<base_type const &>( f ) ) {}
 
-  function(const base_type& f) : base_type(static_cast<const base_type&>(f)){}
+  function( base_type const & f ) : base_type( static_cast<base_type const &>( 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 & operator=( self_type const & f )
   {
       this->assign( f );
       return *this;
   }
 
-  template<typename Functor>
-#ifndef BOOST_NO_SFINAE
-    typename enable_if_c<
-        (boost::type_traits::ice_not<
-        (is_integral<Functor>::value)>::value),
-    self_type&>::type
-#else
-  self_type&
-#endif
-  operator=(Functor const & f)
+  template <typename Functor>
+  BOOST_FUNCTION_ENABLE_IF_NOT_INTEGRAL( Functor, self_type & )
+  operator=( Functor const & f )
   {
     this-> BOOST_NESTED_TEMPLATE assign<Functor>( f );
     return *this;
   }
 
-#ifndef BOOST_NO_SFINAE
-  self_type& operator=(clear_type*)
-  {
-    this->clear();
-    return *this;
-  }
-#endif
+  #ifdef BF_TAKES_FUNCTION_REFERENCES
+      self_type & operator=( typename base_type::signature_type & plain_function_reference )
+      {
+          BF_ASSUME( &plain_function_reference );
+          this->assign( plain_function_reference );
+          return *this;
+      }
+
+      BOOST_FUNCTION_NULL_POINTER_ASSIGNMENT( self_type )
+  #else // BF_TAKES_FUNCTION_REFERENCES
+      self_type & operator=( typename base_type::signature_type * const plain_function_pointer )
+      {
+          this->assign( plain_function_pointer );
+          return *this;
+      }
+  #endif // BF_TAKES_FUNCTION_REFERENCES
 };
 
 #undef BOOST_FUNCTION_PARTIAL_SPEC
@@ -871,6 +868,8 @@
 #undef BOOST_FUNCTION_VOID_RETURN_TYPE
 #undef BOOST_FUNCTION_RETURN
 
+#undef BOOST_FUNCTION_NULL_POINTER_ASSIGNMENT
+
 #if defined(BOOST_MSVC)
 #   pragma warning( pop )
 #endif