1 // 2 // sp_array_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[]> px; 82 BOOST_TEST( !px ); 83 84 BOOST_TEST( X::allocations == 0 ); 85 BOOST_TEST( X::instances == 0 ); 86 87 boost::shared_ptr<X[]> 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[]> 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[]> 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[]> wp( px ); 149 BOOST_TEST( wp.lock() == px ); 150 151 boost::weak_ptr<X[]> 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[]> 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[]> 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 #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES ) 198 199 { 200 std::unique_ptr<X[]> px( new X[ 4 ] ); 201 BOOST_TEST( X::allocations == 1 ); 202 BOOST_TEST( X::instances == 4 ); 203 204 boost::shared_ptr<X[]> px2( std::move( px ) ); 205 BOOST_TEST( X::allocations == 1 ); 206 BOOST_TEST( X::instances == 4 ); 207 BOOST_TEST( px.get() == 0 ); 208 209 try 210 { 211 px2[0].shared_from_this(); 212 BOOST_ERROR( "px2[0].shared_from_this() failed to throw" ); 213 } 214 catch( boost::bad_weak_ptr const& ) 215 { 216 } 217 catch( ... ) 218 { 219 BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" ); 220 } 221 222 px2.reset(); 223 224 BOOST_TEST( X::allocations == 0 ); 225 BOOST_TEST( X::instances == 0 ); 226 } 227 228 { 229 std::unique_ptr<X[]> px( new X[ 4 ] ); 230 BOOST_TEST( X::allocations == 1 ); 231 BOOST_TEST( X::instances == 4 ); 232 233 boost::shared_ptr<X[]> px2; 234 px2 = std::move( px ); 235 BOOST_TEST( X::allocations == 1 ); 236 BOOST_TEST( X::instances == 4 ); 237 BOOST_TEST( px.get() == 0 ); 238 239 try 240 { 241 px2[0].shared_from_this(); 242 BOOST_ERROR( "px2[0].shared_from_this() failed to throw" ); 243 } 244 catch( boost::bad_weak_ptr const& ) 245 { 246 } 247 catch( ... ) 248 { 249 BOOST_ERROR( "px2[0].shared_from_this() threw something else than bad_weak_ptr" ); 250 } 251 252 px2.reset(); 253 254 BOOST_TEST( X::allocations == 0 ); 255 BOOST_TEST( X::instances == 0 ); 256 } 257 258 #endif 259 260 { 261 boost::shared_ptr<X[]> px( new X[ 5 ], array_deleter< X >() ); 262 BOOST_TEST( X::allocations == 1 ); 263 BOOST_TEST( X::instances == 5 ); 264 265 try 266 { 267 px[0].shared_from_this(); 268 BOOST_ERROR( "px[0].shared_from_this() failed to throw" ); 269 } 270 catch( boost::bad_weak_ptr const& ) 271 { 272 } 273 catch( ... ) 274 { 275 BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" ); 276 } 277 278 px.reset(); 279 280 BOOST_TEST( X::allocations == 0 ); 281 BOOST_TEST( X::instances == 0 ); 282 BOOST_TEST( array_deleter< X >::calls == 1 ); 283 } 284 285 { 286 boost::shared_ptr<X[]> px( new X[ 6 ], array_deleter< X >(), std::allocator< X >() ); 287 BOOST_TEST( X::allocations == 1 ); 288 BOOST_TEST( X::instances == 6 ); 289 290 try 291 { 292 px[0].shared_from_this(); 293 BOOST_ERROR( "px[0].shared_from_this() failed to throw" ); 294 } 295 catch( boost::bad_weak_ptr const& ) 296 { 297 } 298 catch( ... ) 299 { 300 BOOST_ERROR( "px[0].shared_from_this() threw something else than bad_weak_ptr" ); 301 } 302 303 px.reset(); 304 305 BOOST_TEST( X::allocations == 0 ); 306 BOOST_TEST( X::instances == 0 ); 307 BOOST_TEST( array_deleter< X >::calls == 2 ); 308 } 309 310 return boost::report_errors(); 311 } 312