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()47 void 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()77 int 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()110 boost::shared_ptr<Y> createY()
111 {
112     boost::shared_ptr<Y> pi(new impl2);
113     return pi;
114 }
115 
test2()116 void 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()127 void 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