]> git.lyx.org Git - lyx.git/blob - boost/boost/shared_ptr.hpp
The std::string mammoth path.
[lyx.git] / boost / boost / shared_ptr.hpp
1 #ifndef BOOST_SHARED_PTR_HPP_INCLUDED
2 #define BOOST_SHARED_PTR_HPP_INCLUDED
3
4 //
5 //  shared_ptr.hpp
6 //
7 //  (C) Copyright Greg Colvin and Beman Dawes 1998, 1999.
8 //  Copyright (c) 2001, 2002, 2003 Peter Dimov
9 //
10 //  Permission to copy, use, modify, sell and distribute this software
11 //  is granted provided this copyright notice appears in all copies.
12 //  This software is provided "as is" without express or implied
13 //  warranty, and with no claim as to its suitability for any purpose.
14 //
15 //  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
16 //
17
18 #include <boost/config.hpp>   // for broken compiler workarounds
19
20 #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
21 #include <boost/detail/shared_ptr_nmt.hpp>
22 #else
23
24 #include <boost/assert.hpp>
25 #include <boost/checked_delete.hpp>
26 #include <boost/throw_exception.hpp>
27 #include <boost/detail/shared_count.hpp>
28 #include <boost/detail/workaround.hpp>
29
30 #include <memory>               // for std::auto_ptr
31 #include <algorithm>            // for std::swap
32 #include <functional>           // for std::less
33 #include <typeinfo>             // for std::bad_cast
34 #include <iosfwd>               // for std::basic_ostream
35
36 #ifdef BOOST_MSVC  // moved here to work around VC++ compiler crash
37 # pragma warning(push)
38 # pragma warning(disable:4284) // odd return type for operator->
39 #endif
40
41 namespace boost
42 {
43
44 template<class T> class weak_ptr;
45 template<class T> class enable_shared_from_this;
46
47 namespace detail
48 {
49
50 struct static_cast_tag {};
51 struct dynamic_cast_tag {};
52 struct polymorphic_cast_tag {};
53
54 template<class T> struct shared_ptr_traits
55 {
56     typedef T & reference;
57 };
58
59 template<> struct shared_ptr_traits<void>
60 {
61     typedef void reference;
62 };
63
64 #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
65
66 template<> struct shared_ptr_traits<void const>
67 {
68     typedef void reference;
69 };
70
71 #endif
72
73 // enable_shared_from_this support
74
75 template<class T, class Y> void sp_enable_shared_from_this(boost::enable_shared_from_this<T> * pe, Y * px, shared_count const & pn)
76 {
77     if(pe != 0) pe->_internal_weak_this._internal_assign(px, pn);
78 }
79
80 inline void sp_enable_shared_from_this(void const *, void const *, shared_count const &)
81 {
82 }
83
84 } // namespace detail
85
86
87 //
88 //  shared_ptr
89 //
90 //  An enhanced relative of scoped_ptr with reference counted copy semantics.
91 //  The object pointed to is deleted when the last shared_ptr pointing to it
92 //  is destroyed or reset.
93 //
94
95 template<class T> class shared_ptr
96 {
97 private:
98
99     // Borland 5.5.1 specific workaround
100     typedef shared_ptr<T> this_type;
101
102 public:
103
104     typedef T element_type;
105     typedef T value_type;
106     typedef T * pointer;
107     typedef typename detail::shared_ptr_traits<T>::reference reference;
108
109     shared_ptr(): px(0), pn() // never throws in 1.30+
110     {
111     }
112
113     template<class Y>
114     explicit shared_ptr(Y * p): px(p), pn(p, checked_deleter<Y>()) // Y must be complete
115     {
116         detail::sp_enable_shared_from_this(p, p, pn);
117     }
118
119     //
120     // Requirements: D's copy constructor must not throw
121     //
122     // shared_ptr will release p by calling d(p)
123     //
124
125     template<class Y, class D> shared_ptr(Y * p, D d): px(p), pn(p, d)
126     {
127         detail::sp_enable_shared_from_this(p, p, pn);
128     }
129
130 //  generated copy constructor, assignment, destructor are fine...
131
132 //  except that Borland C++ has a bug, and g++ with -Wsynth warns
133 #if defined(__BORLANDC__) || defined(__GNUC__)
134
135     shared_ptr & operator=(shared_ptr const & r) // never throws
136     {
137         px = r.px;
138         pn = r.pn; // shared_count::op= doesn't throw
139         return *this;
140     }
141
142 #endif
143
144     template<class Y>
145     explicit shared_ptr(weak_ptr<Y> const & r): pn(r.pn) // may throw
146     {
147         // it is now safe to copy r.px, as pn(r.pn) did not throw
148         px = r.px;
149     }
150
151     template<class Y>
152     shared_ptr(shared_ptr<Y> const & r): px(r.px), pn(r.pn) // never throws
153     {
154     }
155
156     template<class Y>
157     shared_ptr(shared_ptr<Y> const & r, detail::static_cast_tag): px(static_cast<element_type *>(r.px)), pn(r.pn)
158     {
159     }
160
161     template<class Y>
162     shared_ptr(shared_ptr<Y> const & r, detail::dynamic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
163     {
164         if(px == 0) // need to allocate new counter -- the cast failed
165         {
166             pn = detail::shared_count();
167         }
168     }
169
170     template<class Y>
171     shared_ptr(shared_ptr<Y> const & r, detail::polymorphic_cast_tag): px(dynamic_cast<element_type *>(r.px)), pn(r.pn)
172     {
173         if(px == 0)
174         {
175             boost::throw_exception(std::bad_cast());
176         }
177     }
178
179 #ifndef BOOST_NO_AUTO_PTR
180
181     template<class Y>
182     explicit shared_ptr(std::auto_ptr<Y> & r): px(r.get()), pn()
183     {
184         Y * tmp = r.get();
185         pn = detail::shared_count(r);
186         detail::sp_enable_shared_from_this(tmp, tmp, pn);
187     }
188
189 #endif
190
191 #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1200)
192
193     template<class Y>
194     shared_ptr & operator=(shared_ptr<Y> const & r) // never throws
195     {
196         px = r.px;
197         pn = r.pn; // shared_count::op= doesn't throw
198         return *this;
199     }
200
201 #endif
202
203 #ifndef BOOST_NO_AUTO_PTR
204
205     template<class Y>
206     shared_ptr & operator=(std::auto_ptr<Y> & r)
207     {
208         this_type(r).swap(*this);
209         return *this;
210     }
211
212 #endif
213
214     void reset() // never throws in 1.30+
215     {
216         this_type().swap(*this);
217     }
218
219     template<class Y> void reset(Y * p) // Y must be complete
220     {
221         BOOST_ASSERT(p == 0 || p != px); // catch self-reset errors
222         this_type(p).swap(*this);
223     }
224
225     template<class Y, class D> void reset(Y * p, D d)
226     {
227         this_type(p, d).swap(*this);
228     }
229
230     reference operator* () const // never throws
231     {
232         BOOST_ASSERT(px != 0);
233         return *px;
234     }
235
236     T * operator-> () const // never throws
237     {
238         BOOST_ASSERT(px != 0);
239         return px;
240     }
241
242     T * get() const // never throws
243     {
244         return px;
245     }
246
247     // implicit conversion to "bool"
248
249 #if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)
250
251     operator bool () const
252     {
253         return px != 0;
254     }
255
256 #else
257
258     typedef T * (this_type::*unspecified_bool_type)() const;
259
260     operator unspecified_bool_type() const // never throws
261     {
262         return px == 0? 0: &this_type::get;
263     }
264
265 #endif
266
267     // operator! is redundant, but some compilers need it
268
269     bool operator! () const // never throws
270     {
271         return px == 0;
272     }
273
274     bool unique() const // never throws
275     {
276         return pn.unique();
277     }
278
279     long use_count() const // never throws
280     {
281         return pn.use_count();
282     }
283
284     void swap(shared_ptr<T> & other) // never throws
285     {
286         std::swap(px, other.px);
287         pn.swap(other.pn);
288     }
289
290     template<class Y> bool _internal_less(shared_ptr<Y> const & rhs) const
291     {
292         return pn < rhs.pn;
293     }
294
295     void * _internal_get_deleter(std::type_info const & ti) const
296     {
297         return pn.get_deleter(ti);
298     }
299
300 // Tasteless as this may seem, making all members public allows member templates
301 // to work in the absence of member template friends. (Matthew Langston)
302
303 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
304
305 private:
306
307     template<class Y> friend class shared_ptr;
308     template<class Y> friend class weak_ptr;
309
310
311 #endif
312
313     T * px;                     // contained pointer
314     detail::shared_count pn;    // reference counter
315
316 };  // shared_ptr
317
318 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b)
319 {
320     return a.get() == b.get();
321 }
322
323 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b)
324 {
325     return a.get() != b.get();
326 }
327
328 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
329
330 // Resolve the ambiguity between our op!= and the one in rel_ops
331
332 template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b)
333 {
334     return a.get() != b.get();
335 }
336
337 #endif
338
339 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b)
340 {
341     return a._internal_less(b);
342 }
343
344 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b)
345 {
346     a.swap(b);
347 }
348
349 template<class T, class U> shared_ptr<T> static_pointer_cast(shared_ptr<U> const & r)
350 {
351     return shared_ptr<T>(r, detail::static_cast_tag());
352 }
353
354 template<class T, class U> shared_ptr<T> dynamic_pointer_cast(shared_ptr<U> const & r)
355 {
356     return shared_ptr<T>(r, detail::dynamic_cast_tag());
357 }
358
359 // shared_*_cast names are deprecated. Use *_pointer_cast instead.
360
361 template<class T, class U> shared_ptr<T> shared_static_cast(shared_ptr<U> const & r)
362 {
363     return shared_ptr<T>(r, detail::static_cast_tag());
364 }
365
366 template<class T, class U> shared_ptr<T> shared_dynamic_cast(shared_ptr<U> const & r)
367 {
368     return shared_ptr<T>(r, detail::dynamic_cast_tag());
369 }
370
371 template<class T, class U> shared_ptr<T> shared_polymorphic_cast(shared_ptr<U> const & r)
372 {
373     return shared_ptr<T>(r, detail::polymorphic_cast_tag());
374 }
375
376 template<class T, class U> shared_ptr<T> shared_polymorphic_downcast(shared_ptr<U> const & r)
377 {
378     BOOST_ASSERT(dynamic_cast<T *>(r.get()) == r.get());
379     return shared_static_cast<T>(r);
380 }
381
382 // get_pointer() enables boost::mem_fn to recognize shared_ptr
383
384 template<class T> inline T * get_pointer(shared_ptr<T> const & p)
385 {
386     return p.get();
387 }
388
389 // operator<<
390
391 #if defined(__GNUC__) &&  (__GNUC__ < 3)
392
393 template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
394 {
395     os << p.get();
396     return os;
397 }
398
399 #else
400
401 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, <= 1200 && __SGI_STL_PORT)
402 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
403 using std::basic_ostream;
404 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
405 # else
406 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
407 # endif
408 {
409     os << p.get();
410     return os;
411 }
412
413 #endif
414
415 // get_deleter (experimental)
416
417 #if defined(__GNUC__) &&  (__GNUC__ < 3)
418
419 // g++ 2.9x doesn't allow static_cast<X const *>(void *)
420
421 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
422 {
423     void const * q = p._internal_get_deleter(typeid(D));
424     return const_cast<D *>(static_cast<D const *>(q));
425 }
426
427 #else
428
429 template<class D, class T> D * get_deleter(shared_ptr<T> const & p)
430 {
431     return static_cast<D *>(p._internal_get_deleter(typeid(D)));
432 }
433
434 #endif
435
436 } // namespace boost
437
438 #ifdef BOOST_MSVC
439 # pragma warning(pop)
440 #endif
441
442 #endif  // #if defined(BOOST_NO_MEMBER_TEMPLATES) && !defined(BOOST_MSVC6_MEMBER_TEMPLATES)
443
444 #endif  // #ifndef BOOST_SHARED_PTR_HPP_INCLUDED