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