|
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