1 // 2 // shared_from_raw_test - based on shared_from_this_test 3 // 4 // Copyright (c) 2002, 2003, 2014 Peter Dimov 5 // 6 // Distributed under the Boost Software License, Version 1.0. 7 // 8 // See accompanying file LICENSE_1_0.txt or copy at 9 // http://www.boost.org/LICENSE_1_0.txt 10 // 11 12 #include <boost/smart_ptr/enable_shared_from_raw.hpp> 13 #include <boost/shared_ptr.hpp> 14 15 #include <boost/detail/lightweight_test.hpp> 16 17 // 18 19 class X 20 { 21 public: 22 23 virtual void f() = 0; 24 25 protected: 26 ~X()27 ~X() {} 28 }; 29 30 class Y 31 { 32 public: 33 34 virtual boost::shared_ptr<X> getX() = 0; 35 36 protected: 37 ~Y()38 ~Y() {} 39 }; 40 41 boost::shared_ptr<Y> createY(); 42 test()43void test() 44 { 45 boost::shared_ptr<Y> py = createY(); 46 BOOST_TEST(py.get() != 0); 47 BOOST_TEST(py.use_count() == 1); 48 49 try 50 { 51 boost::shared_ptr<X> px = py->getX(); 52 BOOST_TEST(px.get() != 0); 53 BOOST_TEST(py.use_count() == 2); 54 55 px->f(); 56 57 #if !defined( BOOST_NO_RTTI ) 58 boost::shared_ptr<Y> py2 = boost::dynamic_pointer_cast<Y>(px); 59 BOOST_TEST(py.get() == py2.get()); 60 BOOST_TEST(!(py < py2 || py2 < py)); 61 BOOST_TEST(py.use_count() == 3); 62 #endif 63 } 64 catch( boost::bad_weak_ptr const& ) 65 { 66 BOOST_ERROR( "py->getX() failed" ); 67 } 68 } 69 70 void test2(); 71 void test3(); 72 main()73int main() 74 { 75 test(); 76 test2(); 77 test3(); 78 return boost::report_errors(); 79 } 80 81 // virtual inheritance to stress the implementation 82 // (prevents Y* -> impl*, enable_shared_from_raw* -> impl* casts) 83 84 class impl: public X, public virtual Y, public virtual boost::enable_shared_from_raw 85 { 86 public: 87 f()88 virtual void f() 89 { 90 } 91 getX()92 virtual boost::shared_ptr<X> getX() 93 { 94 boost::shared_ptr<impl> pi = boost::shared_from_raw( this ); 95 BOOST_TEST( pi.get() == this ); 96 return pi; 97 } 98 }; 99 100 // intermediate impl2 to stress the implementation 101 102 class impl2: public impl 103 { 104 }; 105 createY()106boost::shared_ptr<Y> createY() 107 { 108 boost::shared_ptr<Y> pi(new impl2); 109 return pi; 110 } 111 test2()112void test2() 113 { 114 boost::shared_ptr<Y> pi(static_cast<impl2*>(0)); 115 } 116 117 // 118 119 struct V: public boost::enable_shared_from_raw 120 { 121 }; 122 test3()123void test3() 124 { 125 boost::shared_ptr<V> p( new V ); 126 127 try 128 { 129 boost::shared_ptr<V> q = boost::shared_from_raw( p.get() ); 130 BOOST_TEST( p == q ); 131 BOOST_TEST( !(p < q) && !(q < p) ); 132 } 133 catch( boost::bad_weak_ptr const & ) 134 { 135 BOOST_ERROR( "shared_from_this( p.get() ) failed" ); 136 } 137 138 V v2( *p ); 139 140 try 141 { 142 // shared_from_raw differs from shared_from_this; 143 // it will not throw here and will create a shared_ptr 144 145 boost::shared_ptr<V> r = boost::shared_from_raw( &v2 ); 146 147 // check if the shared_ptr is correct and that it does 148 // not share ownership with p 149 150 BOOST_TEST( r.get() == &v2 ); 151 BOOST_TEST( p != r ); 152 BOOST_TEST( (p < r) || (r < p) ); 153 } 154 catch( boost::bad_weak_ptr const & ) 155 { 156 BOOST_ERROR("shared_from_raw( &v2 ) failed"); 157 } 158 159 try 160 { 161 *p = V(); 162 boost::shared_ptr<V> r = boost::shared_from_raw( p.get() ); 163 BOOST_TEST( p == r ); 164 BOOST_TEST( !(p < r) && !(r < p) ); 165 } 166 catch( boost::bad_weak_ptr const & ) 167 { 168 BOOST_ERROR("shared_from_raw( p.get() ) threw bad_weak_ptr after *p = V()"); 169 } 170 } 171