1#ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
2#define BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
3
4//
5// intrusive_ptr.hpp
6//
7// Copyright (c) 2001, 2002 Peter Dimov
8//
9// Distributed under the Boost Software License, Version 1.0. (See
10// accompanying file LICENSE_1_0.txt or copy at
11// http://www.boost.org/LICENSE_1_0.txt)
12//
13// See http://www.boost.org/libs/smart_ptr/ for documentation.
14//
15
16#include <boost/smart_ptr/detail/requires_cxx11.hpp>
17
18#include <boost/config.hpp>
19
20#include <boost/assert.hpp>
21#include <boost/config/workaround.hpp>
22#include <boost/smart_ptr/detail/sp_convertible.hpp>
23#include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
24#include <boost/smart_ptr/detail/sp_noexcept.hpp>
25
26#include <boost/config/no_tr1/functional.hpp> // for std::less
27
28#if !defined(BOOST_NO_IOSTREAM)
29#if !defined(BOOST_NO_IOSFWD)
30#include <iosfwd> // for std::basic_ostream
31#else
32#include <ostream>
33#endif
34#endif
35
36
37namespace boost
38{
39
40//
41// intrusive_ptr
42//
43// A smart pointer that uses intrusive reference counting.
44//
45// Relies on unqualified calls to
46//
47// void intrusive_ptr_add_ref(T * p);
48// void intrusive_ptr_release(T * p);
49//
50// (p != 0)
51//
52// The object is responsible for destroying itself.
53//
54
55template<class T> class intrusive_ptr
56{
57private:
58
59 typedef intrusive_ptr this_type;
60
61public:
62
63 typedef T element_type;
64
65 BOOST_CONSTEXPR intrusive_ptr() BOOST_SP_NOEXCEPT : px( 0 )
66 {
67 }
68
69 intrusive_ptr( T * p, bool add_ref = true ): px( p )
70 {
71 if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
72 }
73
74#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
75
76 template<class U>
77#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
78
79 intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() )
80
81#else
82
83 intrusive_ptr( intrusive_ptr<U> const & rhs )
84
85#endif
86 : px( rhs.get() )
87 {
88 if( px != 0 ) intrusive_ptr_add_ref( px );
89 }
90
91#endif
92
93 intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
94 {
95 if( px != 0 ) intrusive_ptr_add_ref( px );
96 }
97
98 ~intrusive_ptr()
99 {
100 if( px != 0 ) intrusive_ptr_release( px );
101 }
102
103#if !defined(BOOST_NO_MEMBER_TEMPLATES) || defined(BOOST_MSVC6_MEMBER_TEMPLATES)
104
105 template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
106 {
107 this_type(rhs).swap(*this);
108 return *this;
109 }
110
111#endif
112
113// Move support
114
115#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
116
117 intrusive_ptr(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT : px( rhs.px )
118 {
119 rhs.px = 0;
120 }
121
122 intrusive_ptr & operator=(intrusive_ptr && rhs) BOOST_SP_NOEXCEPT
123 {
124 this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
125 return *this;
126 }
127
128 template<class U> friend class intrusive_ptr;
129
130 template<class U>
131#if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
132
133 intrusive_ptr(intrusive_ptr<U> && rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty())
134
135#else
136
137 intrusive_ptr(intrusive_ptr<U> && rhs)
138
139#endif
140 : px( rhs.px )
141 {
142 rhs.px = 0;
143 }
144
145 template<class U>
146 intrusive_ptr & operator=(intrusive_ptr<U> && rhs) BOOST_SP_NOEXCEPT
147 {
148 this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
149 return *this;
150 }
151
152#endif
153
154 intrusive_ptr & operator=(intrusive_ptr const & rhs)
155 {
156 this_type(rhs).swap(*this);
157 return *this;
158 }
159
160 intrusive_ptr & operator=(T * rhs)
161 {
162 this_type(rhs).swap(*this);
163 return *this;
164 }
165
166 void reset()
167 {
168 this_type().swap( *this );
169 }
170
171 void reset( T * rhs )
172 {
173 this_type( rhs ).swap( *this );
174 }
175
176 void reset( T * rhs, bool add_ref )
177 {
178 this_type( rhs, add_ref ).swap( *this );
179 }
180
181 T * get() const BOOST_SP_NOEXCEPT
182 {
183 return px;
184 }
185
186 T * detach() BOOST_SP_NOEXCEPT
187 {
188 T * ret = px;
189 px = 0;
190 return ret;
191 }
192
193 T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
194 {
195 BOOST_ASSERT( px != 0 );
196 return *px;
197 }
198
199 T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
200 {
201 BOOST_ASSERT( px != 0 );
202 return px;
203 }
204
205// implicit conversion to "bool"
206#include <boost/smart_ptr/detail/operator_bool.hpp>
207
208 void swap(intrusive_ptr & rhs) BOOST_SP_NOEXCEPT
209 {
210 T * tmp = px;
211 px = rhs.px;
212 rhs.px = tmp;
213 }
214
215private:
216
217 T * px;
218};
219
220template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
221{
222 return a.get() == b.get();
223}
224
225template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
226{
227 return a.get() != b.get();
228}
229
230template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b) BOOST_SP_NOEXCEPT
231{
232 return a.get() == b;
233}
234
235template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b) BOOST_SP_NOEXCEPT
236{
237 return a.get() != b;
238}
239
240template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
241{
242 return a == b.get();
243}
244
245template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b) BOOST_SP_NOEXCEPT
246{
247 return a != b.get();
248}
249
250#if !defined( BOOST_NO_CXX11_NULLPTR )
251
252template<class T> inline bool operator==( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
253{
254 return p.get() == 0;
255}
256
257template<class T> inline bool operator==( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
258{
259 return p.get() == 0;
260}
261
262template<class T> inline bool operator!=( intrusive_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_SP_NOEXCEPT
263{
264 return p.get() != 0;
265}
266
267template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
268{
269 return p.get() != 0;
270}
271
272#endif
273
274template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) BOOST_SP_NOEXCEPT
275{
276 return std::less<T *>()(a.get(), b.get());
277}
278
279template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) BOOST_SP_NOEXCEPT
280{
281 lhs.swap(rhs);
282}
283
284// mem_fn support
285
286template<class T> T * get_pointer(intrusive_ptr<T> const & p) BOOST_SP_NOEXCEPT
287{
288 return p.get();
289}
290
291// pointer casts
292
293template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
294{
295 return static_cast<T *>(p.get());
296}
297
298template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
299{
300 return const_cast<T *>(p.get());
301}
302
303template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
304{
305 return dynamic_cast<T *>(p.get());
306}
307
308#if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
309
310template<class T, class U> intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
311{
312 return intrusive_ptr<T>( static_cast<T*>( p.detach() ), false );
313}
314
315template<class T, class U> intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
316{
317 return intrusive_ptr<T>( const_cast<T*>( p.detach() ), false );
318}
319
320template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) BOOST_SP_NOEXCEPT
321{
322 T * p2 = dynamic_cast<T*>( p.get() );
323
324 intrusive_ptr<T> r( p2, false );
325
326 if( p2 ) p.detach();
327
328 return r;
329}
330
331#endif // defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
332
333// operator<<
334
335#if !defined(BOOST_NO_IOSTREAM)
336
337#if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) && (__GNUC__ < 3) )
338
339template<class Y> std::ostream & operator<< (std::ostream & os, intrusive_ptr<Y> const & p)
340{
341 os << p.get();
342 return os;
343}
344
345#else
346
347// in STLport's no-iostreams mode no iostream symbols can be used
348#ifndef _STLP_NO_IOSTREAMS
349
350# if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
351// MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
352using std::basic_ostream;
353template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
354# else
355template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
356# endif
357{
358 os << p.get();
359 return os;
360}
361
362#endif // _STLP_NO_IOSTREAMS
363
364#endif // __GNUC__ < 3
365
366#endif // !defined(BOOST_NO_IOSTREAM)
367
368// hash_value
369
370template< class T > struct hash;
371
372template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p ) BOOST_SP_NOEXCEPT
373{
374 return boost::hash< T* >()( p.get() );
375}
376
377} // namespace boost
378
379// std::hash
380
381#if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
382
383namespace std
384{
385
386template<class T> struct hash< ::boost::intrusive_ptr<T> >
387{
388 std::size_t operator()( ::boost::intrusive_ptr<T> const & p ) const BOOST_SP_NOEXCEPT
389 {
390 return std::hash< T* >()( p.get() );
391 }
392};
393
394} // namespace std
395
396#endif // #if !defined(BOOST_NO_CXX11_HDR_FUNCTIONAL)
397
398#endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
399

source code of boost/libs/smart_ptr/include/boost/smart_ptr/intrusive_ptr.hpp