1 // 2 // sp_array_n_test.cpp 3 // 4 // Copyright (c) 2012 Peter Dimov 5 // 6 // Distributed under the Boost Software License, Version 1.0. 7 // See accompanying file LICENSE_1_0.txt or copy at 8 // http://www.boost.org/LICENSE_1_0.txt 9 // 10 11 #include <boost/shared_ptr.hpp> 12 #include <boost/weak_ptr.hpp> 13 #include <boost/enable_shared_from_this.hpp> 14 #include <boost/core/lightweight_test.hpp> 15 #include <memory> 16 #include <utility> 17 18 class X: public boost::enable_shared_from_this< X > 19 { 20 public: 21 22 static int allocations; 23 static int instances; 24 X()25 X() 26 { 27 ++instances; 28 } 29 ~X()30 ~X() 31 { 32 --instances; 33 } 34 operator new[](std::size_t n)35 void* operator new[]( std::size_t n ) 36 { 37 ++allocations; 38 return ::operator new[]( n ); 39 } 40 operator delete[](void * p)41 void operator delete[]( void* p ) 42 { 43 --allocations; 44 ::operator delete[]( p ); 45 } 46 47 private: 48 49 X( X const& ); 50 X& operator=( X const& ); 51 }; 52 53 int X::allocations = 0; 54 int X::instances = 0; 55 56 template< class T> class array_deleter 57 { 58 public: 59 60 static int calls; 61 operator ()(T * p) const62 void operator()( T * p ) const 63 { 64 ++calls; 65 delete[] p; 66 } 67 68 private: 69 70 template< class Y > void operator()( Y * p ) const; 71 }; 72 73 template< class T > int array_deleter< T >::calls = 0; 74 main()75int main() 76 { 77 BOOST_TEST( X::allocations == 0 ); 78 BOOST_TEST( X::instances == 0 ); 79 80 { 81 boost::shared_ptr<X[3]> px; 82 BOOST_TEST( !px ); 83 84 BOOST_TEST( X::allocations == 0 ); 85 BOOST_TEST( X::instances == 0 ); 86 87 boost::shared_ptr<X[3]> px2( new X[ 3 ] ); 88 BOOST_TEST( px2 ); 89 90 try 91 { 92 px2[0].shared_from_this(); 93 BOOST_ERROR( "px2[0].shared_from_this() failed to throw" ); 94 } 95 catch( boost::bad_weak_ptr const& ) 96 { 97 } 98 catch( ... ) 99 { 100 BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" ); 101 } 102 103 BOOST_TEST( X::allocations == 1 ); 104 BOOST_TEST( X::instances == 3 ); 105 106 { 107 X & rx = px2[ 0 ]; 108 BOOST_TEST( &rx == px2.get() ); 109 } 110 111 boost::shared_ptr<X const[3]> px3( px2 ); 112 BOOST_TEST( px3 == px2 ); 113 BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) ); 114 115 { 116 X const & rx = px3[ 1 ]; 117 BOOST_TEST( &rx == px3.get() + 1 ); 118 } 119 120 px3.reset(); 121 px3 = px2; 122 BOOST_TEST( px3 == px2 ); 123 BOOST_TEST( !( px2 < px3 ) && !( px3 < px2 ) ); 124 125 boost::shared_ptr<X volatile[3]> px4( px2 ); 126 BOOST_TEST( px4 == px2 ); 127 BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) ); 128 129 { 130 X volatile & rx = px4[ 2 ]; 131 BOOST_TEST( &rx == px4.get() + 2 ); 132 } 133 134 px4.reset(); 135 px4 = px2; 136 BOOST_TEST( px4 == px2 ); 137 BOOST_TEST( !( px2 < px4 ) && !( px4 < px2 ) ); 138 139 boost::shared_ptr<void> px5( px2 ); 140 BOOST_TEST( px5 == px2 ); 141 BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) ); 142 143 px5.reset(); 144 px5 = px2; 145 BOOST_TEST( px5 == px2 ); 146 BOOST_TEST( !( px2 < px5 ) && !( px5 < px2 ) ); 147 148 boost::weak_ptr<X[3]> wp( px ); 149 BOOST_TEST( wp.lock() == px ); 150 151 boost::weak_ptr<X[3]> wp2( px2 ); 152 BOOST_TEST( wp2.lock() == px2 ); 153 154 wp2.reset(); 155 wp2 = px2; 156 BOOST_TEST( wp2.lock() == px2 ); 157 158 boost::weak_ptr<X const[3]> wp3( px2 ); 159 BOOST_TEST( wp3.lock() == px2 ); 160 161 wp3.reset(); 162 wp3 = px2; 163 BOOST_TEST( wp3.lock() == px2 ); 164 165 boost::weak_ptr<X volatile[3]> wp4( px2 ); 166 BOOST_TEST( wp4.lock() == px2 ); 167 168 wp4.reset(); 169 wp4 = px2; 170 BOOST_TEST( wp4.lock() == px2 ); 171 172 boost::weak_ptr<void> wp5( px2 ); 173 BOOST_TEST( wp5.lock() == px2 ); 174 175 wp5.reset(); 176 wp5 = px2; 177 BOOST_TEST( wp5.lock() == px2 ); 178 179 px2.reset(); 180 181 BOOST_TEST( X::allocations == 1 ); 182 BOOST_TEST( X::instances == 3 ); 183 184 px3.reset(); 185 px4.reset(); 186 px5.reset(); 187 188 BOOST_TEST( X::allocations == 0 ); 189 BOOST_TEST( X::instances == 0 ); 190 191 BOOST_TEST( wp2.lock() == 0 ); 192 BOOST_TEST( wp3.lock() == 0 ); 193 BOOST_TEST( wp4.lock() == 0 ); 194 BOOST_TEST( wp5.lock() == 0 ); 195 } 196 197 { 198 boost::shared_ptr<X[5]> px( new X[ 5 ], array_deleter< X >() ); 199 BOOST_TEST( X::allocations == 1 ); 200 BOOST_TEST( X::instances == 5 ); 201 202 try 203 { 204 px[0].shared_from_this(); 205 BOOST_ERROR( "px[0].shared_from_this() failed to throw" ); 206 } 207 catch( boost::bad_weak_ptr const& ) 208 { 209 } 210 catch( ... ) 211 { 212 BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" ); 213 } 214 215 px.reset(); 216 217 BOOST_TEST( X::allocations == 0 ); 218 BOOST_TEST( X::instances == 0 ); 219 BOOST_TEST( array_deleter< X >::calls == 1 ); 220 } 221 222 { 223 boost::shared_ptr<X[6]> px( new X[ 6 ], array_deleter< X >(), std::allocator< X >() ); 224 BOOST_TEST( X::allocations == 1 ); 225 BOOST_TEST( X::instances == 6 ); 226 227 try 228 { 229 px[0].shared_from_this(); 230 BOOST_ERROR( "px[0].shared_from_this() failed to throw" ); 231 } 232 catch( boost::bad_weak_ptr const& ) 233 { 234 } 235 catch( ... ) 236 { 237 BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" ); 238 } 239 240 px.reset(); 241 242 BOOST_TEST( X::allocations == 0 ); 243 BOOST_TEST( X::instances == 0 ); 244 BOOST_TEST( array_deleter< X >::calls == 2 ); 245 } 246 247 return boost::report_errors(); 248 } 249