diff --git a/include/boost/smart_ptr/shared_ptr.hpp b/include/boost/smart_ptr/shared_ptr.hpp index a9e3807..7bcf951 100644 --- a/include/boost/smart_ptr/shared_ptr.hpp +++ b/include/boost/smart_ptr/shared_ptr.hpp @@ -502,9 +502,12 @@ public: boost::detail::sp_assert_convertible< Y, T >(); typename std::unique_ptr< Y, D >::pointer tmp = r.get(); - pn = boost::detail::shared_count( r ); - boost::detail::sp_deleter_construct( this, tmp ); + if( tmp != 0 ) + { + pn = boost::detail::shared_count( r ); + boost::detail::sp_deleter_construct( this, tmp ); + } } #endif @@ -515,9 +518,12 @@ public: boost::detail::sp_assert_convertible< Y, T >(); typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get(); - pn = boost::detail::shared_count( r ); - boost::detail::sp_deleter_construct( this, tmp ); + if( tmp != 0 ) + { + pn = boost::detail::shared_count( r ); + boost::detail::sp_deleter_construct( this, tmp ); + } } // assignment @@ -592,10 +598,13 @@ public: shared_ptr tmp; - tmp.px = p; - tmp.pn = boost::detail::shared_count( r ); + if( p != 0 ) + { + tmp.px = p; + tmp.pn = boost::detail::shared_count( r ); - boost::detail::sp_deleter_construct( &tmp, p ); + boost::detail::sp_deleter_construct( &tmp, p ); + } tmp.swap( *this ); diff --git a/test/sp_bml_unique_ptr_test.cpp b/test/sp_bml_unique_ptr_test.cpp index 0d4921d..e414552 100644 --- a/test/sp_bml_unique_ptr_test.cpp +++ b/test/sp_bml_unique_ptr_test.cpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -66,11 +67,42 @@ struct YD { void operator()( Y* p ) const { - p->deleted_ = true; - delete p; + if( p ) + { + p->deleted_ = true; + delete p; + } + else + { + BOOST_ERROR( "YD::operator()(0) called" ); + } } }; +template static void test_null_unique_ptr( boost::movelib::unique_ptr p1, boost::movelib::unique_ptr p2 ) +{ + BOOST_TEST( T::instances == 0 ); + + boost::shared_ptr sp( boost::move( p1 ) ); + + BOOST_TEST( sp.get() == 0 ); + BOOST_TEST( sp.use_count() == 0 ); + + sp.reset( new T, typename boost::remove_reference::type() ); + + BOOST_TEST( sp.get() != 0 ); + BOOST_TEST( sp.use_count() == 1 ); + + BOOST_TEST( T::instances == 1 ); + + sp = boost::move( p2 ); + + BOOST_TEST( sp.get() == 0 ); + BOOST_TEST( sp.use_count() == 0 ); + + BOOST_TEST( T::instances == 0 ); +} + int main() { { @@ -235,5 +267,28 @@ int main() BOOST_TEST( Y::instances == 0 ); } + { + test_null_unique_ptr( boost::movelib::unique_ptr(), boost::movelib::unique_ptr() ); + test_null_unique_ptr( boost::movelib::unique_ptr(), boost::movelib::unique_ptr() ); + test_null_unique_ptr( boost::movelib::unique_ptr(), boost::movelib::unique_ptr() ); + test_null_unique_ptr( boost::movelib::unique_ptr(), boost::movelib::unique_ptr() ); + } + + { + test_null_unique_ptr( boost::movelib::unique_ptr( 0, YD() ), boost::movelib::unique_ptr( 0, YD() ) ); + test_null_unique_ptr( boost::movelib::unique_ptr( 0, YD() ), boost::movelib::unique_ptr( 0, YD() ) ); + test_null_unique_ptr( boost::movelib::unique_ptr( 0, YD() ), boost::movelib::unique_ptr( 0, YD() ) ); + test_null_unique_ptr( boost::movelib::unique_ptr( 0, YD() ), boost::movelib::unique_ptr( 0, YD() ) ); + } + + { + YD yd; + + test_null_unique_ptr( boost::movelib::unique_ptr( 0, yd ), boost::movelib::unique_ptr( 0, yd ) ); + test_null_unique_ptr( boost::movelib::unique_ptr( 0, yd ), boost::movelib::unique_ptr( 0, yd ) ); + test_null_unique_ptr( boost::movelib::unique_ptr( 0, yd ), boost::movelib::unique_ptr( 0, yd ) ); + test_null_unique_ptr( boost::movelib::unique_ptr( 0, yd ), boost::movelib::unique_ptr( 0, yd ) ); + } + return boost::report_errors(); } diff --git a/test/sp_unique_ptr_test.cpp b/test/sp_unique_ptr_test.cpp index a6d1e4c..8e82959 100644 --- a/test/sp_unique_ptr_test.cpp +++ b/test/sp_unique_ptr_test.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -67,11 +68,42 @@ struct YD { void operator()( Y* p ) const { - p->deleted_ = true; - delete p; + if( p ) + { + p->deleted_ = true; + delete p; + } + else + { + BOOST_ERROR( "YD::operator()(0) called" ); + } } }; +template static void test_null_unique_ptr( std::unique_ptr p1, std::unique_ptr p2 ) +{ + BOOST_TEST( T::instances == 0 ); + + boost::shared_ptr sp( std::move( p1 ) ); + + BOOST_TEST( sp.get() == 0 ); + BOOST_TEST( sp.use_count() == 0 ); + + sp.reset( new T, typename boost::remove_reference::type() ); + + BOOST_TEST( sp.get() != 0 ); + BOOST_TEST( sp.use_count() == 1 ); + + BOOST_TEST( T::instances == 1 ); + + sp = std::move( p2 ); + + BOOST_TEST( sp.get() == 0 ); + BOOST_TEST( sp.use_count() == 0 ); + + BOOST_TEST( T::instances == 0 ); +} + int main() { { @@ -226,6 +258,29 @@ int main() BOOST_TEST( Y::instances == 0 ); } + { + test_null_unique_ptr( std::unique_ptr(), std::unique_ptr() ); + test_null_unique_ptr( std::unique_ptr(), std::unique_ptr() ); + test_null_unique_ptr( std::unique_ptr(), std::unique_ptr() ); + test_null_unique_ptr( std::unique_ptr(), std::unique_ptr() ); + } + + { + test_null_unique_ptr( std::unique_ptr( 0, YD() ), std::unique_ptr( 0, YD() ) ); + test_null_unique_ptr( std::unique_ptr( 0, YD() ), std::unique_ptr( 0, YD() ) ); + test_null_unique_ptr( std::unique_ptr( 0, YD() ), std::unique_ptr( 0, YD() ) ); + test_null_unique_ptr( std::unique_ptr( 0, YD() ), std::unique_ptr( 0, YD() ) ); + } + + { + YD yd; + + test_null_unique_ptr( std::unique_ptr( 0, yd ), std::unique_ptr( 0, yd ) ); + test_null_unique_ptr( std::unique_ptr( 0, yd ), std::unique_ptr( 0, yd ) ); + test_null_unique_ptr( std::unique_ptr( 0, yd ), std::unique_ptr( 0, yd ) ); + test_null_unique_ptr( std::unique_ptr( 0, yd ), std::unique_ptr( 0, yd ) ); + } + return boost::report_errors(); }