1 // 2 // esft_regtest.cpp 3 // 4 // A regression test for enable_shared_from_this 5 // 6 // Copyright (c) 2008 Peter Dimov 7 // 8 // Distributed under the Boost Software License, Version 1.0. 9 // 10 // See accompanying file LICENSE_1_0.txt or copy at 11 // http://www.boost.org/LICENSE_1_0.txt) 12 // 13 14 #include <boost/enable_shared_from_this.hpp> 15 #include <boost/shared_ptr.hpp> 16 #include <boost/weak_ptr.hpp> 17 #include <boost/detail/lightweight_test.hpp> 18 #include <memory> 19 #include <string> 20 21 class X: public boost::enable_shared_from_this< X > 22 { 23 private: 24 25 int destroyed_; 26 int deleted_; 27 int expected_; 28 29 private: 30 31 X( X const& ); 32 X& operator=( X const& ); 33 34 public: 35 36 static int instances; 37 38 public: 39 X(int expected)40 explicit X( int expected ): destroyed_( 0 ), deleted_( 0 ), expected_( expected ) 41 { 42 ++instances; 43 } 44 ~X()45 ~X() 46 { 47 BOOST_TEST( deleted_ == expected_ ); 48 BOOST_TEST( destroyed_ == 0 ); 49 ++destroyed_; 50 --instances; 51 } 52 53 typedef void (*deleter_type)( X* ); 54 deleter(X * px)55 static void deleter( X * px ) 56 { 57 ++px->deleted_; 58 } 59 deleter2(X * px)60 static void deleter2( X * px ) 61 { 62 ++px->deleted_; 63 delete px; 64 } 65 }; 66 67 int X::instances = 0; 68 test()69void test() 70 { 71 BOOST_TEST( X::instances == 0 ); 72 73 { 74 X x( 0 ); 75 BOOST_TEST( X::instances == 1 ); 76 } 77 78 BOOST_TEST( X::instances == 0 ); 79 80 { 81 std::auto_ptr<X> px( new X( 0 ) ); 82 BOOST_TEST( X::instances == 1 ); 83 } 84 85 BOOST_TEST( X::instances == 0 ); 86 87 { 88 boost::shared_ptr<X> px( new X( 0 ) ); 89 BOOST_TEST( X::instances == 1 ); 90 91 boost::weak_ptr<X> wp( px ); 92 BOOST_TEST( !wp.expired() ); 93 94 px.reset(); 95 96 BOOST_TEST( wp.expired() ); 97 } 98 99 BOOST_TEST( X::instances == 0 ); 100 101 { 102 X x( 1 ); 103 boost::shared_ptr<X> px( &x, X::deleter ); 104 BOOST_TEST( X::instances == 1 ); 105 106 X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px ); 107 BOOST_TEST( pd != 0 && *pd == X::deleter ); 108 109 boost::weak_ptr<X> wp( px ); 110 BOOST_TEST( !wp.expired() ); 111 112 px.reset(); 113 114 BOOST_TEST( wp.expired() ); 115 } 116 117 BOOST_TEST( X::instances == 0 ); 118 119 { 120 boost::shared_ptr<X> px( new X( 1 ), X::deleter2 ); 121 BOOST_TEST( X::instances == 1 ); 122 123 X::deleter_type * pd = boost::get_deleter<X::deleter_type>( px ); 124 BOOST_TEST( pd != 0 && *pd == X::deleter2 ); 125 126 boost::weak_ptr<X> wp( px ); 127 BOOST_TEST( !wp.expired() ); 128 129 px.reset(); 130 131 BOOST_TEST( wp.expired() ); 132 } 133 134 BOOST_TEST( X::instances == 0 ); 135 } 136 137 struct V: public boost::enable_shared_from_this<V> 138 { ~VV139 virtual ~V() {} 140 std::string m_; 141 }; 142 143 struct V2 144 { ~V2V2145 virtual ~V2() {} 146 std::string m2_; 147 }; 148 149 struct W: V2, V 150 { 151 }; 152 test2()153void test2() 154 { 155 boost::shared_ptr<W> p( new W ); 156 } 157 test3()158void test3() 159 { 160 V * p = new W; 161 boost::shared_ptr<void> pv( p ); 162 BOOST_TEST( pv.get() == p ); 163 BOOST_TEST( pv.use_count() == 1 ); 164 } 165 166 struct null_deleter 167 { operator ()null_deleter168 void operator()( void const* ) const {} 169 }; 170 test4()171void test4() 172 { 173 boost::shared_ptr<V> pv( new V ); 174 boost::shared_ptr<V> pv2( pv.get(), null_deleter() ); 175 BOOST_TEST( pv2.get() == pv.get() ); 176 BOOST_TEST( pv2.use_count() == 1 ); 177 } 178 test5()179void test5() 180 { 181 V v; 182 183 boost::shared_ptr<V> p1( &v, null_deleter() ); 184 BOOST_TEST( p1.get() == &v ); 185 BOOST_TEST( p1.use_count() == 1 ); 186 187 try 188 { 189 p1->shared_from_this(); 190 } 191 catch( ... ) 192 { 193 BOOST_ERROR( "p1->shared_from_this() failed" ); 194 } 195 196 p1.reset(); 197 198 boost::shared_ptr<V> p2( &v, null_deleter() ); 199 BOOST_TEST( p2.get() == &v ); 200 BOOST_TEST( p2.use_count() == 1 ); 201 202 try 203 { 204 p2->shared_from_this(); 205 } 206 catch( ... ) 207 { 208 BOOST_ERROR( "p2->shared_from_this() failed" ); 209 } 210 } 211 main()212int main() 213 { 214 test(); 215 test2(); 216 test3(); 217 test4(); 218 test5(); 219 220 return boost::report_errors(); 221 } 222