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