Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r81253 - in trunk: boost/smart_ptr boost/smart_ptr/detail libs/smart_ptr/test
From: pdimov_at_[hidden]
Date: 2012-11-08 13:07:51


Author: pdimov
Date: 2012-11-08 13:07:49 EST (Thu, 08 Nov 2012)
New Revision: 81253
URL: http://svn.boost.org/trac/boost/changeset/81253

Log:
Add support for shared_ptr<X[N>.
Added:
   trunk/libs/smart_ptr/test/sp_array_n_test.cpp (contents, props changed)
Text files modified:
   trunk/boost/smart_ptr/detail/sp_convertible.hpp | 5 +++
   trunk/boost/smart_ptr/shared_ptr.hpp | 53 +++++++++++++++++++++++++++++++++++++--
   trunk/libs/smart_ptr/test/Jamfile.v2 | 1
   trunk/libs/smart_ptr/test/sp_array_cv_test.cpp | 50 +++++++++++++++++++++++++------------
   trunk/libs/smart_ptr/test/sp_convertible_test.cpp | 2
   5 files changed, 91 insertions(+), 20 deletions(-)

Modified: trunk/boost/smart_ptr/detail/sp_convertible.hpp
==============================================================================
--- trunk/boost/smart_ptr/detail/sp_convertible.hpp (original)
+++ trunk/boost/smart_ptr/detail/sp_convertible.hpp 2012-11-08 13:07:49 EST (Thu, 08 Nov 2012)
@@ -58,6 +58,11 @@
     enum _vt { value = sp_convertible< Y[1], T[1] >::value };
 };
 
+template< class Y, std::size_t N, class T > struct sp_convertible< Y[N], T[] >
+{
+ enum _vt { value = sp_convertible< Y[1], T[1] >::value };
+};
+
 struct sp_empty
 {
 };

Modified: trunk/boost/smart_ptr/shared_ptr.hpp
==============================================================================
--- trunk/boost/smart_ptr/shared_ptr.hpp (original)
+++ trunk/boost/smart_ptr/shared_ptr.hpp 2012-11-08 13:07:49 EST (Thu, 08 Nov 2012)
@@ -81,6 +81,11 @@
     typedef T type;
 };
 
+template< class T, std::size_t N > struct sp_element< T[N] >
+{
+ typedef T type;
+};
+
 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
 
 // sp_dereference, return type of operator*
@@ -121,6 +126,11 @@
     typedef void type;
 };
 
+template< class T, std::size_t N > struct sp_dereference< T[N] >
+{
+ typedef void type;
+};
+
 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
 
 // sp_member_access, return type of operator->
@@ -137,6 +147,11 @@
     typedef void type;
 };
 
+template< class T, std::size_t N > struct sp_member_access< T[N] >
+{
+ typedef void type;
+};
+
 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
 
 // sp_array_access, return type of operator[]
@@ -153,6 +168,27 @@
     typedef T & type;
 };
 
+template< class T, std::size_t N > struct sp_array_access< T[N] >
+{
+ typedef T & type;
+};
+
+#endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+// sp_extent, for operator[] index check
+
+template< class T > struct sp_extent
+{
+ enum _vt { value = 0 };
+};
+
+#if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
+
+template< class T, std::size_t N > struct sp_extent< T[N] >
+{
+ enum _vt { value = N };
+};
+
 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
 
 // enable_shared_from_this support
@@ -207,8 +243,9 @@
 
 template< class Y, class T > inline void sp_assert_convertible()
 {
- T* p = static_cast< Y* >( 0 );
- (void)p;
+ // static_assert( sp_convertible< Y, T >::value );
+ typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ];
+ (void)sizeof( tmp );
 }
 
 // pointer constructor helper
@@ -224,7 +261,12 @@
 template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
 {
     sp_assert_convertible< Y[], T[] >();
+ boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
+}
 
+template< class T, std::size_t N, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
+{
+ sp_assert_convertible< Y[N], T[N] >();
     boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
 }
 
@@ -244,6 +286,11 @@
     sp_assert_convertible< Y[], T[] >();
 }
 
+template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
+{
+ sp_assert_convertible< Y[N], T[N] >();
+}
+
 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
 
 } // namespace detail
@@ -547,7 +594,7 @@
     typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const // never throws
     {
         BOOST_ASSERT( px != 0 );
- BOOST_ASSERT( i >= 0 );
+ BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
 
         return px[ i ];
     }

Modified: trunk/libs/smart_ptr/test/Jamfile.v2
==============================================================================
--- trunk/libs/smart_ptr/test/Jamfile.v2 (original)
+++ trunk/libs/smart_ptr/test/Jamfile.v2 2012-11-08 13:07:49 EST (Thu, 08 Nov 2012)
@@ -73,6 +73,7 @@
           [ run sp_array_test.cpp ]
           [ compile sp_array_cv_test.cpp ]
           [ run sp_convertible_test.cpp ]
+ [ run sp_array_n_test.cpp ]
 
           [ compile-fail array_fail_spa_sp_c.cpp ]
           [ compile-fail array_fail_sp_spa_c.cpp ]

Modified: trunk/libs/smart_ptr/test/sp_array_cv_test.cpp
==============================================================================
--- trunk/libs/smart_ptr/test/sp_array_cv_test.cpp (original)
+++ trunk/libs/smart_ptr/test/sp_array_cv_test.cpp 2012-11-08 13:07:49 EST (Thu, 08 Nov 2012)
@@ -14,29 +14,47 @@
 {
 };
 
-int main()
+class B
 {
- boost::shared_ptr< X[] > px;
+};
 
- boost::shared_ptr< X const[] > pcx( px );
- boost::shared_ptr< X volatile[] > pvx( px );
+class D: public B
+{
+};
 
- boost::shared_ptr< X const volatile[] > pcvx( px );
- boost::shared_ptr< X const volatile[] > pcvx2( pcx );
- boost::shared_ptr< X const volatile[] > pcvx3( pvx );
+#define TEST_CONV( T, U ) \
+ { \
+ boost::shared_ptr< T > p1; \
+ boost::shared_ptr< U > p2( p1 ); \
+ p2 = p1; \
+ boost::shared_ptr< U > p3 = boost::shared_ptr< T >(); \
+ p3 = boost::shared_ptr< T >(); \
+ }
+
+#define TEST_CV_TRUE( T, U ) \
+ TEST_CONV( T, U ) \
+ TEST_CONV( T, const U ) \
+ TEST_CONV( T, volatile U ) \
+ TEST_CONV( T, const volatile U ) \
+ TEST_CONV( const T, const U ) \
+ TEST_CONV( const T, const volatile U ) \
+ TEST_CONV( volatile T, volatile U ) \
+ TEST_CONV( volatile T, const volatile U ) \
+ TEST_CONV( const volatile T, const volatile U )
 
- boost::shared_ptr< void > pv( px );
+int main()
+{
+ TEST_CV_TRUE( X, X )
+ TEST_CV_TRUE( X, void )
+ TEST_CV_TRUE( D, B )
 
- boost::shared_ptr< void const > pcv( px );
- boost::shared_ptr< void const > pcv2( pcx );
+ TEST_CV_TRUE( X[], X[] )
+ TEST_CV_TRUE( X[3], X[3] )
 
- boost::shared_ptr< void volatile > pvv( px );
- boost::shared_ptr< void volatile > pvv2( pvx );
+ TEST_CV_TRUE( X[3], X[] )
 
- boost::shared_ptr< void const volatile > pcvv( px );
- boost::shared_ptr< void const volatile > pcvv2( pcx );
- boost::shared_ptr< void const volatile > pcvv3( pvx );
- boost::shared_ptr< void const volatile > pcvv4( pcvx );
+ TEST_CV_TRUE( X[], void )
+ TEST_CV_TRUE( X[3], void )
 
     return 0;
 }

Added: trunk/libs/smart_ptr/test/sp_array_n_test.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/smart_ptr/test/sp_array_n_test.cpp 2012-11-08 13:07:49 EST (Thu, 08 Nov 2012)
@@ -0,0 +1,248 @@
+//
+// sp_array_n_test.cpp
+//
+// Copyright (c) 2012 Peter Dimov
+//
+// Distributed under 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
+//
+
+#include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
+#include <boost/enable_shared_from_this.hpp>
+#include <boost/detail/lightweight_test.hpp>
+#include <memory>
+#include <utility>
+
+class X: public boost::enable_shared_from_this< X >
+{
+public:
+
+ static int allocations;
+ static int instances;
+
+ X()
+ {
+ ++instances;
+ }
+
+ ~X()
+ {
+ --instances;
+ }
+
+ void* operator new[]( std::size_t n )
+ {
+ ++allocations;
+ return ::operator new[]( n );
+ }
+
+ void operator delete[]( void* p )
+ {
+ --allocations;
+ ::operator delete[]( p );
+ }
+
+private:
+
+ X( X const& );
+ X& operator=( X const& );
+};
+
+int X::allocations = 0;
+int X::instances = 0;
+
+template< class T> class array_deleter
+{
+public:
+
+ static int calls;
+
+ void operator()( T * p ) const
+ {
+ ++calls;
+ delete[] p;
+ }
+
+private:
+
+ template< class Y > void operator()( Y * p ) const;
+};
+
+template< class T > int array_deleter< T >::calls = 0;
+
+int main()
+{
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ {
+ boost::shared_ptr<X[3]> px;
+ BOOST_TEST( !px );
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ boost::shared_ptr<X[3]> px2( new X[ 3 ] );
+ BOOST_TEST( px2 );
+
+ try
+ {
+ px2[0].shared_from_this();
+ BOOST_ERROR( "px2[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 3 );
+
+ {
+ X & rx = px2[ 0 ];
+ BOOST_TEST( &rx == px2.get() );
+ }
+
+ boost::shared_ptr<X const[3]> px3( px2 );
+ BOOST_TEST( px3 == px2 );
+ BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
+
+ {
+ X const & rx = px3[ 1 ];
+ BOOST_TEST( &rx == px3.get() + 1 );
+ }
+
+ px3.reset();
+ px3 = px2;
+ BOOST_TEST( px3 == px2 );
+ BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) );
+
+ boost::shared_ptr<X volatile[3]> px4( px2 );
+ BOOST_TEST( px4 == px2 );
+ BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
+
+ {
+ X volatile & rx = px4[ 2 ];
+ BOOST_TEST( &rx == px4.get() + 2 );
+ }
+
+ px4.reset();
+ px4 = px2;
+ BOOST_TEST( px4 == px2 );
+ BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) );
+
+ boost::shared_ptr<void> px5( px2 );
+ BOOST_TEST( px5 == px2 );
+ BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
+
+ px5.reset();
+ px5 = px2;
+ BOOST_TEST( px5 == px2 );
+ BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) );
+
+ boost::weak_ptr<X[3]> wp( px );
+ BOOST_TEST( wp.lock() == px );
+
+ boost::weak_ptr<X[3]> wp2( px2 );
+ BOOST_TEST( wp2.lock() == px2 );
+
+ wp2.reset();
+ wp2 = px2;
+ BOOST_TEST( wp2.lock() == px2 );
+
+ boost::weak_ptr<X const[3]> wp3( px2 );
+ BOOST_TEST( wp3.lock() == px2 );
+
+ wp3.reset();
+ wp3 = px2;
+ BOOST_TEST( wp3.lock() == px2 );
+
+ boost::weak_ptr<X volatile[3]> wp4( px2 );
+ BOOST_TEST( wp4.lock() == px2 );
+
+ wp4.reset();
+ wp4 = px2;
+ BOOST_TEST( wp4.lock() == px2 );
+
+ boost::weak_ptr<void> wp5( px2 );
+ BOOST_TEST( wp5.lock() == px2 );
+
+ wp5.reset();
+ wp5 = px2;
+ BOOST_TEST( wp5.lock() == px2 );
+
+ px2.reset();
+
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 3 );
+
+ px3.reset();
+ px4.reset();
+ px5.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+
+ BOOST_TEST( wp2.lock() == 0 );
+ BOOST_TEST( wp3.lock() == 0 );
+ BOOST_TEST( wp4.lock() == 0 );
+ BOOST_TEST( wp5.lock() == 0 );
+ }
+
+ {
+ boost::shared_ptr<X[5]> px( new X[ 5 ], array_deleter< X >() );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 5 );
+
+ try
+ {
+ px[0].shared_from_this();
+ BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( array_deleter< X >::calls == 1 );
+ }
+
+ {
+ boost::shared_ptr<X[6]> px( new X[ 6 ], array_deleter< X >(), std::allocator< X >() );
+ BOOST_TEST( X::allocations == 1 );
+ BOOST_TEST( X::instances == 6 );
+
+ try
+ {
+ px[0].shared_from_this();
+ BOOST_ERROR( "px[0].shared_from_this() failed to throw" );
+ }
+ catch( boost::bad_weak_ptr const& )
+ {
+ }
+ catch( ... )
+ {
+ BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" );
+ }
+
+ px.reset();
+
+ BOOST_TEST( X::allocations == 0 );
+ BOOST_TEST( X::instances == 0 );
+ BOOST_TEST( array_deleter< X >::calls == 2 );
+ }
+
+ return boost::report_errors();
+}

Modified: trunk/libs/smart_ptr/test/sp_convertible_test.cpp
==============================================================================
--- trunk/libs/smart_ptr/test/sp_convertible_test.cpp (original)
+++ trunk/libs/smart_ptr/test/sp_convertible_test.cpp 2012-11-08 13:07:49 EST (Thu, 08 Nov 2012)
@@ -78,7 +78,7 @@
     TEST_CV_FALSE( X[3], X[4] )
     TEST_CV_FALSE( D[3], B[3] )
 
- //TEST_CV_TRUE( X[3], X[] )
+ TEST_CV_TRUE( X[3], X[] )
     TEST_CV_FALSE( X[], X[3] )
 
     TEST_CV_TRUE( X[], void )


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