Boost logo

Boost-Commit :

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


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