Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r60875 - in sandbox/function/boost/function: . detail
From: dsaritz_at_[hidden]
Date: 2010-03-27 11:19:07


Author: psiha
Date: 2010-03-27 11:19:07 EDT (Sat, 27 Mar 2010)
New Revision: 60875
URL: http://svn.boost.org/trac/boost/changeset/60875

Log:
Added the safe_bool utility class/header. Used it to replace to current 'safe bool' implementation (which was also buggy because it used the same type for all function<> instantiations).

Fixed a bug that caused a wrong vtable_for_functor() overload to be chosen when assigning function<> object to another function<> object of the same type/instantiation.

Minor other cleanup and stylistic changes.
Added:
   sandbox/function/boost/function/detail/safe_bool.hpp (contents, props changed)
Text files modified:
   sandbox/function/boost/function/function_base.hpp | 5 ++---
   sandbox/function/boost/function/function_template.hpp | 18 +++++-------------
   2 files changed, 7 insertions(+), 16 deletions(-)

Added: sandbox/function/boost/function/detail/safe_bool.hpp
==============================================================================
--- (empty file)
+++ sandbox/function/boost/function/detail/safe_bool.hpp 2010-03-27 11:19:07 EDT (Sat, 27 Mar 2010)
@@ -0,0 +1,161 @@
+////////////////////////////////////////////////////////////////////////////////
+///
+/// \file safe_bool.hpp
+/// -------------------
+///
+/// Utility class and macros for reducing boilerplate code related to
+/// 'unspecified_bool_type' implementation.
+///
+/// Copyright (c) Domagoj Saric 2010.
+///
+/// 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
+////////////////////////////////////////////////////////////////////////////////
+//------------------------------------------------------------------------------
+#pragma once
+#ifndef safe_bool_hpp__7E590FD4_CE99_442C_82DB_8DC9CB7D3886
+#define safe_bool_hpp__7E590FD4_CE99_442C_82DB_8DC9CB7D3886
+//------------------------------------------------------------------------------
+#include "boost/mpl/bool.hpp"
+//------------------------------------------------------------------------------
+namespace boost
+{
+//------------------------------------------------------------------------------
+
+// Taken from funtion/function_template.hpp
+#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
+ // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
+ #define BOOST_NO_SAFE_BOOL
+#endif
+
+template <class T>
+class safe_bool
+{
+#ifndef BOOST_NO_SAFE_BOOL
+private:
+ struct unspecified_bool_type_helper
+ {
+ void member_function() {};
+ int member_data_;
+ };
+
+ typedef void (unspecified_bool_type_helper::*unspecified_bool_type_function) ();
+ typedef int unspecified_bool_type_helper::*unspecified_bool_type_data ;
+
+ union fast_safe_bool
+ {
+ unsigned long plain_pointer_placeholder;
+ unspecified_bool_type_function pointer_to_member ;
+ };
+
+ // It is assumed that if the compiler is able to fit a plain, single
+ // inheritance member function pointer into sizeof( void * ) that its null
+ // binary representation is identical to a plain null void pointer (all bits
+ // zeroed). Without a way to check this at compile time this asserted at
+ // runtime.
+ // The above need not hold for data member pointers (e.g. MSVC++ uses -1
+ // for null-data member pointers).
+ typedef mpl::bool_
+ <
+ ( sizeof( fast_safe_bool ) <= sizeof( unsigned long ) )
+ > can_use_fast_bool_hack;
+
+protected:
+ typedef typename mpl::if_
+ <
+ can_use_fast_bool_hack,
+ unspecified_bool_type_function,
+ unspecified_bool_type_data
+ >::type unspecified_bool_type;
+
+private:
+ static
+ unspecified_bool_type_function
+ make_safe_bool_standard_worker( bool const bool_value, unspecified_bool_type_function const null_value )
+ {
+ return bool_value ? &unspecified_bool_type_helper::member_function : null_value;
+ }
+ static
+ unspecified_bool_type_data
+ make_safe_bool_standard_worker( bool const bool_value, unspecified_bool_type_data const null_value )
+ {
+ return bool_value ? &unspecified_bool_type_helper::member_data_ : null_value;
+ }
+
+ static
+ unspecified_bool_type make_safe_bool_worker( bool const value, mpl::false_ /*use standard version*/ )
+ {
+ return make_safe_bool_standard_worker( value, unspecified_bool_type( 0 ) );
+ }
+
+ static
+ unspecified_bool_type make_safe_bool_worker( bool const value, mpl::true_ /*use fast-hack version*/ )
+ {
+ fast_safe_bool const fastSafeBool = { value };
+ assert
+ (
+ ( !!fastSafeBool.pointer_to_member == !!value ) &&
+ "The void-pointer-sized member pointer null binary"
+ "representation assumption does not hold for this"
+ "compiler/platform."
+ );
+ return fastSafeBool.pointer_to_member;
+ }
+
+public:
+ typedef unspecified_bool_type type;
+
+ template <typename implicit_bool>
+ static type make( implicit_bool const value )
+ {
+ return make_safe_bool_worker( !!value, can_use_fast_bool_hack() );
+ }
+
+#else // BOOST_NO_SAFE_BOOL
+public:
+ typedef bool unspecified_bool_type;
+ typedef unspecified_bool_type type;
+
+ template <typename implicit_bool>
+ static type make( implicit_bool const value )
+ {
+ return !!value;
+ }
+#endif // BOOST_NO_SAFE_BOOL
+}; // namespace detail
+
+
+
+// If we could use member pointers before the member is actually declared/seen
+// we could use CRTP-based helper classes for minimum verbosity safe_bool
+// implementations:
+// template <class Base, bool (Base::*bool_function) () const>
+// class safe_bool
+// {
+// operator unspecified_bool_type() const { return make_safe_bool( static_cast<Base const *>( this )->*bool_function() ); }
+// };
+//
+// class my_class : public safe_bool<my_class, &my_class::valid>
+//...
+
+//...instead we are left with macros...
+#define BOOST_SAFE_BOOL_FROM_FUNCTION( classType, constMemberFunction ) \
+ operator boost::safe_bool<classType>::type() const { return boost::safe_bool<classType>::make( constMemberFunction() ); }
+
+#define BOOST_SAFE_BOOL_FROM_DATA( classType, constMemberData ) \
+ operator boost::safe_bool<classType>::type() const { return boost::safe_bool<classType>::make( constMemberData ); }
+
+#define BOOST_SAFE_BOOL_FOR_TEMPLATE_FROM_FUNCTION( classType, constMemberFunction ) \
+ operator typename boost::safe_bool<classType>::type() const { return boost::safe_bool<classType>::make( constMemberFunction() ); }
+
+#define BOOST_SAFE_BOOL_FOR_TEMPLATE_FROM_DATA( classType, constMemberData ) \
+ operator typename boost::safe_bool<classType>::type() const { return boost::safe_bool<classType>::make( constMemberData ); }
+
+
+//------------------------------------------------------------------------------
+} // namespace boost
+//------------------------------------------------------------------------------
+#endif // safe_bool_hpp

Modified: sandbox/function/boost/function/function_base.hpp
==============================================================================
--- sandbox/function/boost/function/function_base.hpp (original)
+++ sandbox/function/boost/function/function_base.hpp 2010-03-27 11:19:07 EDT (Sat, 27 Mar 2010)
@@ -61,6 +61,8 @@
 #include <boost/function_equal.hpp>
 #include <boost/function/function_fwd.hpp>
 
+#include <boost/function/detail/safe_bool.hpp>
+
 #if defined(BOOST_MSVC)
 # pragma warning( push )
 # pragma warning( disable : 4127 ) // "conditional expression is constant"
@@ -1253,9 +1255,6 @@
       this->swap<EmptyHandler>( tmp, empty_handler_vtable );
   }
 
- struct dummy { void nonnull() {}; };
- typedef void (dummy::*safe_bool)();
-
 private:
     #ifdef BOOST_MSVC
     // MSVC (9.0 SP1) inlines this even with /Oxs for (probably) no gain so we

Modified: sandbox/function/boost/function/function_template.hpp
==============================================================================
--- sandbox/function/boost/function/function_template.hpp (original)
+++ sandbox/function/boost/function/function_template.hpp 2010-03-27 11:19:07 EDT (Sat, 27 Mar 2010)
@@ -382,16 +382,9 @@
         return function_base::swap<base_empty_handler>( other, empty_handler_vtable() );
     }
 
-#if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG)
- // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it
- operator bool () const { return !this->empty(); }
-#else
   public:
- operator safe_bool () const
- { return (this->empty())? 0 : &dummy::nonnull; }
-
+ BOOST_SAFE_BOOL_FOR_TEMPLATE_FROM_FUNCTION( BOOST_FUNCTION_FUNCTION, !empty );
     bool operator!() const { return this->empty(); }
-#endif
 
 private:
     static vtable_type const & empty_handler_vtable() { return vtable_for_functor<base_empty_handler>( my_empty_handler() ); }
@@ -461,20 +454,19 @@
 
     // This overload should not actually be for a 'complete' BOOST_FUNCTION_FUNCTION as it is enough
         // for the signature template parameter to be the same (and therefor the vtable is the same, with
- // a possibly exception being the case of an empty source as empty handler vtables depend on the
+ // a possible exception being the case of an empty source as empty handler vtables depend on the
         // policy as well as the signature).
     template <typename ActualFunctor>
     static vtable_type const & vtable_for_functor( BOOST_FUNCTION_FUNCTION const & functor )
     {
- BOOST_STATIC_ASSERT(( is_same<ActualFunctor, BOOST_FUNCTION_FUNCTION>::value ));
+ BOOST_STATIC_ASSERT(( is_base_of<BOOST_FUNCTION_FUNCTION, ActualFunctor>::value ));
       return functor.get_vtable();
     }
 
     template <typename ActualFunctor, typename StoredFunctor>
- static vtable_type const & vtable_for_functor( StoredFunctor const & /*functor*/ )
+ typename disable_if<is_base_of<BOOST_FUNCTION_FUNCTION, StoredFunctor>, vtable_type const &>::type
+ static vtable_for_functor( StoredFunctor const & /*functor*/ )
     {
- BOOST_STATIC_ASSERT(( !is_same<StoredFunctor, BOOST_FUNCTION_FUNCTION>::value ));
-
       using namespace detail::function;
 
       // A minimally typed manager is used for the invoker (anti-code-bloat).


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