From 592795e00be4e9a1671a4fac377fbce97dd00705 Mon Sep 17 00:00:00 2001 From: Christopher Hite Date: Mon, 5 Mar 2012 19:13:54 +0000 Subject: [PATCH] has_trivial_copy and basic copy optimization done [SVN r77237] --- include/boost/optional/optional.hpp | 84 ++++++++++++++++++++--- test/optional_test_trivial_assertions.cpp | 19 +++++ 2 files changed, 92 insertions(+), 11 deletions(-) diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp index 4d58093..602690c 100644 --- a/include/boost/optional/optional.hpp +++ b/include/boost/optional/optional.hpp @@ -27,9 +27,13 @@ #include #include #include +#include +#include #include #include #include +#include +#include #include #include #include @@ -172,6 +176,16 @@ struct types_when_is_ref template struct optional_dtor_optimized : has_trivial_destructor {}; +template +struct optional_copy_optimized : mpl::or_< + is_reference, // refs aren't copyable at all, but optional should be copy_optimized + mpl::and_< + has_trivial_copy, + has_trivial_assign, + mpl::bool_< (sizeof(T) <= 128) > // TODO make 128 configurable + > +> {}; + struct optional_tag {} ; template @@ -204,6 +218,7 @@ class optional_base : public optional_tag public: typedef BOOST_DEDUCED_TYPENAME mpl::if_::type types ; typedef optional_dtor_optimized dtor_optimized; + typedef optional_copy_optimized copy_optimized; protected: typedef bool (this_type::*unspecified_bool_type)() const; @@ -247,9 +262,7 @@ class optional_base : public optional_tag // Creates a deep copy of another optional // Can throw if T::T(T const&) does - optional_base ( optional_base const& rhs ) - : - m_initialized(false) + void optional_base_copy_ctor_impl ( optional_base const& rhs ) { if ( rhs.is_initialized() ) construct(rhs.get_impl()); @@ -506,6 +519,59 @@ class optional_base : public optional_tag storage_type m_storage ; } ; + +template +struct optional_copier : optional_base +{ + // does copy and assignment optimization + typedef optional_detail::optional_base base ; + typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ; + + optional_copier () {} + + optional_copier ( optional_copier const& rhs ) : base() + { + optional_base_copy_ctor_impl(rhs); + } + + optional_copier& operator= ( optional_copier const& rhs ) + { + this->assign( static_cast(rhs) ) ; + return *this ; + } + + template + explicit optional_copier ( Expr expr ) : base(expr) {} + + template + explicit optional_copier ( P1 p1 ,P2 p2 ) : base(p1,p2) {} + + optional_copier ( bool cond, argument_type val ) : base(cond,val) {} +}; + + +template +struct optional_copier : optional_base +{ + // does copy and assignment optimization + typedef optional_detail::optional_base base ; + typedef BOOST_DEDUCED_TYPENAME base::argument_type argument_type ; + + optional_copier () {} + + //optional_copier ( optional_copier const& rhs ) // default impl does memcpy + + //optional_copier& operator= ( optional_copier const& rhs ) // default impl does memcpy + + template + explicit optional_copier ( Expr expr ) : base(expr) {} + + template + explicit optional_copier ( P1 p1 ,P2 p2 ) : base(p1,p2) {} + + optional_copier ( bool cond, argument_type val ) : base(cond,val) {} +}; + template struct optional_dtor_mixin{ ~optional_dtor_mixin(){ static_cast(this)->destructor_impl() ; } @@ -518,10 +584,10 @@ struct optional_dtor_mixin { }; template class optional : - public optional_detail::optional_base, + public optional_detail::optional_copier::copy_optimized::value >, public optional_detail::optional_dtor_mixin, optional_detail::optional_base::dtor_optimized::value > { - typedef optional_detail::optional_base base ; + typedef optional_detail::optional_copier::copy_optimized::value > base ; typedef BOOST_DEDUCED_TYPENAME base::unspecified_bool_type unspecified_bool_type ; @@ -584,7 +650,7 @@ class optional : // Creates a deep copy of another optional // Can throw if T::T(T const&) does - optional ( optional const& rhs ) : base( static_cast(rhs) ) {} + //optional ( optional const& rhs ) // default impl (see optional_copier) // No-throw (assuming T::~T() doesn't) //~optional() {} @@ -616,11 +682,7 @@ class optional : // Assigns from another optional (deep-copies the rhs value) // Basic Guarantee: If T::T( T const& ) throws, this is left UNINITIALIZED // (NOTE: On BCB, this operator is not actually called and left is left UNMODIFIED in case of a throw) - optional& operator= ( optional const& rhs ) - { - this->assign( static_cast(rhs) ) ; - return *this ; - } + //optional& operator= ( optional const& rhs ) // default impl (see optional_copier) // Assigns from a T (deep-copies the rhs value) // Basic Guarantee: If T::( T const& ) throws, this is left UNINITIALIZED diff --git a/test/optional_test_trivial_assertions.cpp b/test/optional_test_trivial_assertions.cpp index 4a565c0..d96e50d 100644 --- a/test/optional_test_trivial_assertions.cpp +++ b/test/optional_test_trivial_assertions.cpp @@ -6,6 +6,7 @@ using namespace boost; typedef optional oc; typedef optional oi; +typedef optional of; typedef optional os; BOOST_STATIC_ASSERT( sizeof(oc) <= 2*sizeof(char) ); @@ -15,8 +16,26 @@ BOOST_STATIC_ASSERT( !has_trivial_default_constructor::value ); //never tru BOOST_STATIC_ASSERT( !has_trivial_default_constructor::value ); BOOST_STATIC_ASSERT( has_trivial_destructor::value ); //should be true where has_trivial_destructor +BOOST_STATIC_ASSERT( has_trivial_destructor::value ); BOOST_STATIC_ASSERT( !has_trivial_destructor::value ); +BOOST_STATIC_ASSERT( has_trivial_copy::value ); //should be true where has_trivial_copy +BOOST_STATIC_ASSERT( has_trivial_copy::value ); +BOOST_STATIC_ASSERT( !has_trivial_copy::value ); + +BOOST_STATIC_ASSERT( has_trivial_assign::value ); //should be true where has_trivial_assign +BOOST_STATIC_ASSERT( has_trivial_assign::value ); +BOOST_STATIC_ASSERT( !has_trivial_assign::value ); + +BOOST_STATIC_ASSERT( oi::dtor_optimized::value ); +BOOST_STATIC_ASSERT( oi::copy_optimized::value ); + + +BOOST_STATIC_ASSERT( of::dtor_optimized::value ); +BOOST_STATIC_ASSERT( of::copy_optimized::value ); + + + /* has_trivial_assign