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()43 void 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()73 int 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()106 boost::shared_ptr<Y> createY()
107 {
108     boost::shared_ptr<Y> pi(new impl2);
109     return pi;
110 }
111 
test2()112 void 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()123 void 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