1 #include <boost/config.hpp>
2 
3 #if defined(BOOST_MSVC)
4 
5 #pragma warning(disable: 4786)  // identifier truncated in debug info
6 #pragma warning(disable: 4710)  // function not inlined
7 #pragma warning(disable: 4711)  // function selected for automatic inline expansion
8 #pragma warning(disable: 4514)  // unreferenced inline removed
9 #pragma warning(disable: 4355)  // 'this' : used in base member initializer list
10 #pragma warning(disable: 4511)  // copy constructor could not be generated
11 #pragma warning(disable: 4512)  // assignment operator could not be generated
12 
13 #if (BOOST_MSVC >= 1310)
14 #pragma warning(disable: 4675)  // resolved overload found with Koenig lookup
15 #endif
16 
17 #endif
18 
19 //
20 //  intrusive_ptr_move_test.cpp
21 //
22 //  Copyright (c) 2002-2005 Peter Dimov
23 //
24 // Distributed under the Boost Software License, Version 1.0. (See
25 // accompanying file LICENSE_1_0.txt or copy at
26 // http://www.boost.org/LICENSE_1_0.txt)
27 //
28 
29 #include <boost/detail/lightweight_test.hpp>
30 #include <boost/intrusive_ptr.hpp>
31 #include <boost/detail/atomic_count.hpp>
32 #include <boost/config.hpp>
33 #include <utility>
34 
35 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
36 
37 namespace N
38 {
39 
40 class base
41 {
42 private:
43 
44     mutable boost::detail::atomic_count use_count_;
45 
46     base(base const &);
47     base & operator=(base const &);
48 
49 protected:
50 
base()51     base(): use_count_(0)
52     {
53         ++instances;
54     }
55 
~base()56     virtual ~base()
57     {
58         --instances;
59     }
60 
61 public:
62 
63     static long instances;
64 
use_count() const65     long use_count() const
66     {
67         return use_count_;
68     }
69 
70 #if !defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
71 
intrusive_ptr_add_ref(base const * p)72     inline friend void intrusive_ptr_add_ref(base const * p)
73     {
74         ++p->use_count_;
75     }
76 
intrusive_ptr_release(base const * p)77     inline friend void intrusive_ptr_release(base const * p)
78     {
79         if(--p->use_count_ == 0) delete p;
80     }
81 
82 #else
83 
add_ref() const84     void add_ref() const
85     {
86         ++use_count_;
87     }
88 
release() const89     void release() const
90     {
91         if(--use_count_ == 0) delete this;
92     }
93 
94 #endif
95 };
96 
97 long base::instances = 0;
98 
99 } // namespace N
100 
101 #if defined(BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP)
102 
103 namespace boost
104 {
105 
intrusive_ptr_add_ref(N::base const * p)106 inline void intrusive_ptr_add_ref(N::base const * p)
107 {
108     p->add_ref();
109 }
110 
intrusive_ptr_release(N::base const * p)111 inline void intrusive_ptr_release(N::base const * p)
112 {
113     p->release();
114 }
115 
116 } // namespace boost
117 
118 #endif
119 
120 //
121 
122 struct X: public virtual N::base
123 {
124 };
125 
126 struct Y: public X
127 {
128 };
129 
main()130 int main()
131 {
132     BOOST_TEST( N::base::instances == 0 );
133 
134     {
135         boost::intrusive_ptr<X> p( new X );
136         BOOST_TEST( N::base::instances == 1 );
137 
138         boost::intrusive_ptr<X> p2( std::move( p ) );
139         BOOST_TEST( N::base::instances == 1 );
140         BOOST_TEST( p.get() == 0 );
141 
142         p2.reset();
143         BOOST_TEST( N::base::instances == 0 );
144     }
145 
146     {
147         boost::intrusive_ptr<Y> p( new Y );
148         BOOST_TEST( N::base::instances == 1 );
149 
150         boost::intrusive_ptr<X> p2( std::move( p ) );
151         BOOST_TEST( N::base::instances == 1 );
152         BOOST_TEST( p.get() == 0 );
153 
154         p2.reset();
155         BOOST_TEST( N::base::instances == 0 );
156     }
157 
158     {
159         boost::intrusive_ptr<X> p( new X );
160         BOOST_TEST( N::base::instances == 1 );
161 
162         boost::intrusive_ptr<X> p2;
163         p2 = std::move( p );
164         BOOST_TEST( N::base::instances == 1 );
165         BOOST_TEST( p.get() == 0 );
166 
167         p2.reset();
168         BOOST_TEST( N::base::instances == 0 );
169     }
170 
171     {
172         boost::intrusive_ptr<X> p( new X );
173         BOOST_TEST( N::base::instances == 1 );
174 
175         boost::intrusive_ptr<X> p2( new X );
176         BOOST_TEST( N::base::instances == 2 );
177         p2 = std::move( p );
178         BOOST_TEST( N::base::instances == 1 );
179         BOOST_TEST( p.get() == 0 );
180 
181         p2.reset();
182         BOOST_TEST( N::base::instances == 0 );
183     }
184 
185     {
186         boost::intrusive_ptr<Y> p( new Y );
187         BOOST_TEST( N::base::instances == 1 );
188 
189         boost::intrusive_ptr<X> p2;
190         p2 = std::move( p );
191         BOOST_TEST( N::base::instances == 1 );
192         BOOST_TEST( p.get() == 0 );
193 
194         p2.reset();
195         BOOST_TEST( N::base::instances == 0 );
196     }
197 
198     {
199         boost::intrusive_ptr<Y> p( new Y );
200         BOOST_TEST( N::base::instances == 1 );
201 
202         boost::intrusive_ptr<X> p2( new X );
203         BOOST_TEST( N::base::instances == 2 );
204         p2 = std::move( p );
205         BOOST_TEST( N::base::instances == 1 );
206         BOOST_TEST( p.get() == 0 );
207 
208         p2.reset();
209         BOOST_TEST( N::base::instances == 0 );
210     }
211 
212     {
213         boost::intrusive_ptr<X> px( new Y );
214 
215         X * px2 = px.get();
216 
217         boost::intrusive_ptr<Y> py = boost::static_pointer_cast<Y>( std::move( px ) );
218         BOOST_TEST( py.get() == px2 );
219         BOOST_TEST( px.get() == 0 );
220         BOOST_TEST( py->use_count() == 1 );
221     }
222 
223     BOOST_TEST( N::base::instances == 0 );
224 
225     {
226         boost::intrusive_ptr<X const> px( new X );
227 
228         X const * px2 = px.get();
229 
230         boost::intrusive_ptr<X> px3 = boost::const_pointer_cast<X>( std::move( px ) );
231         BOOST_TEST( px3.get() == px2 );
232         BOOST_TEST( px.get() == 0 );
233         BOOST_TEST( px3->use_count() == 1 );
234     }
235 
236     BOOST_TEST( N::base::instances == 0 );
237 
238     {
239         boost::intrusive_ptr<X> px( new Y );
240 
241         X * px2 = px.get();
242 
243         boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( std::move( px ) );
244         BOOST_TEST( py.get() == px2 );
245         BOOST_TEST( px.get() == 0 );
246         BOOST_TEST( py->use_count() == 1 );
247     }
248 
249     BOOST_TEST( N::base::instances == 0 );
250 
251     {
252         boost::intrusive_ptr<X> px( new X );
253 
254         X * px2 = px.get();
255 
256         boost::intrusive_ptr<Y> py = boost::dynamic_pointer_cast<Y>( std::move( px ) );
257         BOOST_TEST( py.get() == 0 );
258         BOOST_TEST( px.get() == px2 );
259         BOOST_TEST( px->use_count() == 1 );
260     }
261 
262     BOOST_TEST( N::base::instances == 0 );
263 
264     return boost::report_errors();
265 }
266 
267 #else // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
268 
main()269 int main()
270 {
271     return 0;
272 }
273 
274 #endif
275