diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index 8dab621..cb9eeb4 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -387,8 +387,8 @@ public: { typedef typename sp_convert_reference::type D2; - D2 d2( r.get_deleter() ); - pi_ = new sp_counted_impl_pd< typename std::unique_ptr::pointer, D2 >( r.get(), d2 ); + D2 d2( static_cast( r.get_deleter() ) ); + pi_ = new sp_counted_impl_pd< typename std::unique_ptr::pointer, D2 >( r.get(), static_cast< D2&& >( d2 ) ); #ifdef BOOST_NO_EXCEPTIONS diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp index 56b9efa..0cbb2ce 100644 --- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp @@ -145,7 +145,7 @@ template class BOOST_SYMBOL_VISIBLE sp_counted_impl_pd: public private: P ptr; // copy constructor must not throw - D del; // copy constructor must not throw + D del; // copy/move constructor must not throw sp_counted_impl_pd( sp_counted_impl_pd const & ); sp_counted_impl_pd & operator= ( sp_counted_impl_pd const & ); @@ -160,6 +160,14 @@ public: { } +#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + + sp_counted_impl_pd( P p, D && d ): ptr( p ), del( static_cast< D&& >( d ) ) + { + } + +#endif + sp_counted_impl_pd( P p ): ptr( p ), del() { } diff --git a/test/Jamfile b/test/Jamfile index adb9960..69a68a5 100644 --- a/test/Jamfile +++ b/test/Jamfile @@ -408,3 +408,5 @@ run wp_unordered_test.cpp ; run owner_hash_test.cpp ; run sp_unordered_test.cpp ; + +run sp_unique_ptr_test2.cpp ; diff --git a/test/sp_unique_ptr_test2.cpp b/test/sp_unique_ptr_test2.cpp new file mode 100644 index 0000000..9964e3c --- /dev/null +++ b/test/sp_unique_ptr_test2.cpp @@ -0,0 +1,101 @@ +// Copyright 2021 Peter Dimov +// Distributed under the Boost Software License, Version 1.0. +// https://www.boost.org/LICENSE_1_0.txt + +#include +#include +#include +#include +#include +#include + +#if defined( BOOST_NO_CXX11_SMART_PTR ) + +BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_NO_CXX11_SMART_PTR is defined") +int main() {} + +#elif defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) + +BOOST_PRAGMA_MESSAGE("Skipping test because BOOST_NO_CXX11_RVALUE_REFERENCES is defined") +int main() {} + +#else + +struct Y +{ + static int instances; + + bool deleted_; + + Y(): deleted_( false ) + { + ++instances; + } + + ~Y() + { + BOOST_TEST( deleted_ ); + --instances; + } + +private: + + Y( Y const & ); + Y & operator=( Y const & ); +}; + +int Y::instances = 0; + +struct YD +{ + bool moved_; + + YD(): moved_( false ) + { + } + + YD( YD&& r ): moved_( false ) + { + r.moved_ = true; + } + + void operator()( Y* p ) const + { + BOOST_TEST( !moved_ ); + + if( p ) + { + p->deleted_ = true; + delete p; + } + else + { + BOOST_ERROR( "YD::operator()(0) called" ); + } + } + +private: + + YD( YD const & ); + YD & operator=( YD const & ); +}; + +int main() +{ + BOOST_TEST( Y::instances == 0 ); + + std::unique_ptr p( new Y ); + BOOST_TEST( Y::instances == 1 ); + + boost::shared_ptr p2( std::move( p ) ); + BOOST_TEST( Y::instances == 1 ); + BOOST_TEST( p.get() == 0 ); + BOOST_TEST( p.get_deleter().moved_ ); + + p2.reset(); + BOOST_TEST( Y::instances == 0 ); + + return boost::report_errors(); +} + +#endif