diff --git a/include/boost/smart_ptr/shared_array.hpp b/include/boost/smart_ptr/shared_array.hpp index 36799e6..3e79582 100644 --- a/include/boost/smart_ptr/shared_array.hpp +++ b/include/boost/smart_ptr/shared_array.hpp @@ -5,7 +5,7 @@ // shared_array.hpp // // (C) Copyright Greg Colvin and Beman Dawes 1998, 1999. -// Copyright (c) 2001, 2002 Peter Dimov +// Copyright (c) 2001, 2002, 2012 Peter Dimov // // Distributed under the Boost Software License, Version 1.0. (See // accompanying file LICENSE_1_0.txt or copy at @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -55,18 +56,32 @@ public: typedef T element_type; - explicit shared_array(T * p = 0): px(p), pn(p, deleter()) + shared_array(): px( 0 ), pn() // never throws { } + template + explicit shared_array( Y * p ): px( p ), pn( p, checked_array_deleter() ) + { + boost::detail::sp_assert_convertible< Y[], T[] >(); + } + // // Requirements: D's copy constructor must not throw // // shared_array will release p by calling d(p) // - template shared_array(T * p, D d): px(p), pn(p, d) + template shared_array( Y * p, D d ): px( p ), pn( p, d ) { + boost::detail::sp_assert_convertible< Y[], T[] >(); + } + + // As above, but with allocator. A's copy constructor shall not throw. + + template shared_array( Y * p, D d, A a ): px( p ), pn( p, d, a ) + { + boost::detail::sp_assert_convertible< Y[], T[] >(); } // generated copy constructor, destructor are fine... @@ -79,8 +94,38 @@ public: { } + shared_array( shared_array && r ): px( r.px ), pn() // never throws + { + pn.swap( r.pn ); + r.px = 0; + } + #endif + // conversion + + template +#if !defined( BOOST_SP_NO_SP_CONVERTIBLE ) + + shared_array( shared_array const & r, typename boost::detail::sp_enable_if_convertible< Y[], T[] >::type = boost::detail::sp_empty() ) + +#else + + shared_array( shared_array const & r ) + +#endif + : px( r.px ), pn( r.pn ) // never throws + { + boost::detail::sp_assert_convertible< Y[], T[] >(); + } + + // aliasing + + template< class Y > + shared_array( shared_array const & r, element_type * p ): px( p ), pn( r.pn ) // never throws + { + } + // assignment shared_array & operator=( shared_array const & r ) // never throws @@ -89,15 +134,58 @@ public: return *this; } - void reset(T * p = 0) +#if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400) + + template + shared_array & operator=( shared_array const & r ) // never throws { - BOOST_ASSERT(p == 0 || p != px); - this_type(p).swap(*this); + this_type( r ).swap( *this ); + return *this; } - template void reset(T * p, D d) +#endif + +#if defined( BOOST_HAS_RVALUE_REFS ) + + shared_array & operator=( shared_array && r ) // never throws { - this_type(p, d).swap(*this); + this_type( static_cast< shared_array && >( r ) ).swap( *this ); + return *this; + } + + template + shared_array & operator=( shared_array && r ) // never throws + { + this_type( static_cast< shared_array && >( r ) ).swap( *this ); + return *this; + } + +#endif + + void reset() // never throws + { + this_type().swap( *this ); + } + + template void reset( Y * p ) // Y must be complete + { + BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors + this_type( p ).swap( *this ); + } + + template void reset( Y * p, D d ) + { + this_type( p, d ).swap( *this ); + } + + template void reset( Y * p, D d, A a ) + { + this_type( p, d, a ).swap( *this ); + } + + template void reset( shared_array const & r, element_type * p ) + { + this_type( r, p ).swap( *this ); } T & operator[] (std::ptrdiff_t i) const // never throws @@ -138,6 +226,8 @@ public: private: + template friend class shared_array; + T * px; // contained pointer detail::shared_count pn; // reference counter diff --git a/test/smart_ptr_test.cpp b/test/smart_ptr_test.cpp index 7b4de34..656a42a 100644 --- a/test/smart_ptr_test.cpp +++ b/test/smart_ptr_test.cpp @@ -236,7 +236,7 @@ void test() ca2.reset(); BOOST_TEST( ca.use_count() == 2 ); BOOST_TEST( ca3.use_count() == 2 ); - BOOST_TEST( ca2.use_count() == 1 ); + BOOST_TEST( ca2.use_count() == 0 ); ca.reset(); BOOST_TEST( ca.get() == 0 ); @@ -269,7 +269,7 @@ void test() udta2.reset(); BOOST_TEST( udta2.get() == 0 ); BOOST_TEST( udta.use_count() == 1 ); - BOOST_TEST( udta2.use_count() == 1 ); + BOOST_TEST( udta2.use_count() == 0 ); BOOST_TEST( UDT_use_count == 4 ); // reality check