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