]> git.lyx.org Git - lyx.git/blob - boost/boost/smart_ptr/shared_ptr.hpp
Cmake export tests: More tests to be inverted, suspended or made non-standard
[lyx.git] / boost / boost / smart_ptr / shared_ptr.hpp
1 #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED
2 #define BOOST_SMART_PTR_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-2008 Peter Dimov
9 //
10 //  Distributed under the Boost Software License, Version 1.0. (See
11 //  accompanying file LICENSE_1_0.txt or copy at
12 //  http://www.boost.org/LICENSE_1_0.txt)
13 //
14 //  See http://www.boost.org/libs/smart_ptr/shared_ptr.htm for documentation.
15 //
16
17 #include <boost/config.hpp>   // for broken compiler workarounds
18
19 // In order to avoid circular dependencies with Boost.TR1
20 // we make sure that our include of <memory> doesn't try to
21 // pull in the TR1 headers: that's why we use this header 
22 // rather than including <memory> directly:
23 #include <boost/config/no_tr1/memory.hpp>  // std::auto_ptr
24
25 #include <boost/assert.hpp>
26 #include <boost/checked_delete.hpp>
27 #include <boost/throw_exception.hpp>
28 #include <boost/smart_ptr/detail/shared_count.hpp>
29 #include <boost/detail/workaround.hpp>
30 #include <boost/smart_ptr/detail/sp_convertible.hpp>
31 #include <boost/smart_ptr/detail/sp_nullptr_t.hpp>
32
33 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
34 #include <boost/smart_ptr/detail/spinlock_pool.hpp>
35 #endif
36
37 #include <algorithm>            // for std::swap
38 #include <functional>           // for std::less
39 #include <typeinfo>             // for std::bad_cast
40 #include <cstddef>              // for std::size_t
41
42 #if !defined(BOOST_NO_IOSTREAM)
43 #if !defined(BOOST_NO_IOSFWD)
44 #include <iosfwd>               // for std::basic_ostream
45 #else
46 #include <ostream>
47 #endif
48 #endif
49
50 namespace boost
51 {
52
53 template<class T> class shared_ptr;
54 template<class T> class weak_ptr;
55 template<class T> class enable_shared_from_this;
56 class enable_shared_from_raw;
57
58 namespace movelib
59 {
60
61     template< class T, class D > class unique_ptr;
62
63 } // namespace movelib
64
65 namespace detail
66 {
67
68 // sp_element, element_type
69
70 template< class T > struct sp_element
71 {
72     typedef T type;
73 };
74
75 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
76
77 template< class T > struct sp_element< T[] >
78 {
79     typedef T type;
80 };
81
82 #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
83
84 template< class T, std::size_t N > struct sp_element< T[N] >
85 {
86     typedef T type;
87 };
88
89 #endif
90
91 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
92
93 // sp_dereference, return type of operator*
94
95 template< class T > struct sp_dereference
96 {
97     typedef T & type;
98 };
99
100 template<> struct sp_dereference< void >
101 {
102     typedef void type;
103 };
104
105 #if !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
106
107 template<> struct sp_dereference< void const >
108 {
109     typedef void type;
110 };
111
112 template<> struct sp_dereference< void volatile >
113 {
114     typedef void type;
115 };
116
117 template<> struct sp_dereference< void const volatile >
118 {
119     typedef void type;
120 };
121
122 #endif // !defined(BOOST_NO_CV_VOID_SPECIALIZATIONS)
123
124 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
125
126 template< class T > struct sp_dereference< T[] >
127 {
128     typedef void type;
129 };
130
131 #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
132
133 template< class T, std::size_t N > struct sp_dereference< T[N] >
134 {
135     typedef void type;
136 };
137
138 #endif
139
140 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
141
142 // sp_member_access, return type of operator->
143
144 template< class T > struct sp_member_access
145 {
146     typedef T * type;
147 };
148
149 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
150
151 template< class T > struct sp_member_access< T[] >
152 {
153     typedef void type;
154 };
155
156 #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
157
158 template< class T, std::size_t N > struct sp_member_access< T[N] >
159 {
160     typedef void type;
161 };
162
163 #endif
164
165 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
166
167 // sp_array_access, return type of operator[]
168
169 template< class T > struct sp_array_access
170 {
171     typedef void type;
172 };
173
174 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
175
176 template< class T > struct sp_array_access< T[] >
177 {
178     typedef T & type;
179 };
180
181 #if !defined( __BORLANDC__ ) || !BOOST_WORKAROUND( __BORLANDC__, < 0x600 )
182
183 template< class T, std::size_t N > struct sp_array_access< T[N] >
184 {
185     typedef T & type;
186 };
187
188 #endif
189
190 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
191
192 // sp_extent, for operator[] index check
193
194 template< class T > struct sp_extent
195 {
196     enum _vt { value = 0 };
197 };
198
199 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
200
201 template< class T, std::size_t N > struct sp_extent< T[N] >
202 {
203     enum _vt { value = N };
204 };
205
206 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
207
208 // enable_shared_from_this support
209
210 template< class X, class Y, class T > inline void sp_enable_shared_from_this( boost::shared_ptr<X> const * ppx, Y const * py, boost::enable_shared_from_this< T > const * pe )
211 {
212     if( pe != 0 )
213     {
214         pe->_internal_accept_owner( ppx, const_cast< Y* >( py ) );
215     }
216 }
217
218 template< class X, class Y > inline void sp_enable_shared_from_this( boost::shared_ptr<X> * ppx, Y const * py, boost::enable_shared_from_raw const * pe );
219
220 #ifdef _MANAGED
221
222 // Avoid C4793, ... causes native code generation
223
224 struct sp_any_pointer
225 {
226     template<class T> sp_any_pointer( T* ) {}
227 };
228
229 inline void sp_enable_shared_from_this( sp_any_pointer, sp_any_pointer, sp_any_pointer )
230 {
231 }
232
233 #else // _MANAGED
234
235 inline void sp_enable_shared_from_this( ... )
236 {
237 }
238
239 #endif // _MANAGED
240
241 #if !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION ) && !defined( BOOST_NO_AUTO_PTR )
242
243 // rvalue auto_ptr support based on a technique by Dave Abrahams
244
245 template< class T, class R > struct sp_enable_if_auto_ptr
246 {
247 };
248
249 template< class T, class R > struct sp_enable_if_auto_ptr< std::auto_ptr< T >, R >
250 {
251     typedef R type;
252 }; 
253
254 #endif
255
256 // sp_assert_convertible
257
258 template< class Y, class T > inline void sp_assert_convertible()
259 {
260 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
261
262     // static_assert( sp_convertible< Y, T >::value );
263     typedef char tmp[ sp_convertible< Y, T >::value? 1: -1 ];
264     (void)sizeof( tmp );
265
266 #else
267
268     T* p = static_cast< Y* >( 0 );
269     (void)p;
270
271 #endif
272 }
273
274 // pointer constructor helper
275
276 template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T > * ppx, Y * p, boost::detail::shared_count & pn )
277 {
278     boost::detail::shared_count( p ).swap( pn );
279     boost::detail::sp_enable_shared_from_this( ppx, p, p );
280 }
281
282 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
283
284 template< class T, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
285 {
286     sp_assert_convertible< Y[], T[] >();
287     boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
288 }
289
290 template< class T, std::size_t N, class Y > inline void sp_pointer_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * p, boost::detail::shared_count & pn )
291 {
292     sp_assert_convertible< Y[N], T[N] >();
293     boost::detail::shared_count( p, boost::checked_array_deleter< T >() ).swap( pn );
294 }
295
296 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
297
298 // deleter constructor helper
299
300 template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T > * ppx, Y * p )
301 {
302     boost::detail::sp_enable_shared_from_this( ppx, p, p );
303 }
304
305 #if !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
306
307 template< class T, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[] > * /*ppx*/, Y * /*p*/ )
308 {
309     sp_assert_convertible< Y[], T[] >();
310 }
311
312 template< class T, std::size_t N, class Y > inline void sp_deleter_construct( boost::shared_ptr< T[N] > * /*ppx*/, Y * /*p*/ )
313 {
314     sp_assert_convertible< Y[N], T[N] >();
315 }
316
317 #endif // !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
318
319 } // namespace detail
320
321
322 //
323 //  shared_ptr
324 //
325 //  An enhanced relative of scoped_ptr with reference counted copy semantics.
326 //  The object pointed to is deleted when the last shared_ptr pointing to it
327 //  is destroyed or reset.
328 //
329
330 template<class T> class shared_ptr
331 {
332 private:
333
334     // Borland 5.5.1 specific workaround
335     typedef shared_ptr<T> this_type;
336
337 public:
338
339     typedef typename boost::detail::sp_element< T >::type element_type;
340
341     shared_ptr() BOOST_NOEXCEPT : px( 0 ), pn() // never throws in 1.30+
342     {
343     }
344
345 #if !defined( BOOST_NO_CXX11_NULLPTR )
346
347     shared_ptr( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT : px( 0 ), pn() // never throws
348     {
349     }
350
351 #endif
352
353     template<class Y>
354     explicit shared_ptr( Y * p ): px( p ), pn() // Y must be complete
355     {
356         boost::detail::sp_pointer_construct( this, p, pn );
357     }
358
359     //
360     // Requirements: D's copy constructor must not throw
361     //
362     // shared_ptr will release p by calling d(p)
363     //
364
365     template<class Y, class D> shared_ptr( Y * p, D d ): px( p ), pn( p, d )
366     {
367         boost::detail::sp_deleter_construct( this, p );
368     }
369
370 #if !defined( BOOST_NO_CXX11_NULLPTR )
371
372     template<class D> shared_ptr( boost::detail::sp_nullptr_t p, D d ): px( p ), pn( p, d )
373     {
374     }
375
376 #endif
377
378     // As above, but with allocator. A's copy constructor shall not throw.
379
380     template<class Y, class D, class A> shared_ptr( Y * p, D d, A a ): px( p ), pn( p, d, a )
381     {
382         boost::detail::sp_deleter_construct( this, p );
383     }
384
385 #if !defined( BOOST_NO_CXX11_NULLPTR )
386
387     template<class D, class A> shared_ptr( boost::detail::sp_nullptr_t p, D d, A a ): px( p ), pn( p, d, a )
388     {
389     }
390
391 #endif
392
393 //  generated copy constructor, destructor are fine...
394
395 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
396
397 // ... except in C++0x, move disables the implicit copy
398
399     shared_ptr( shared_ptr const & r ) BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
400     {
401     }
402
403 #endif
404
405     template<class Y>
406     explicit shared_ptr( weak_ptr<Y> const & r ): pn( r.pn ) // may throw
407     {
408         boost::detail::sp_assert_convertible< Y, T >();
409
410         // it is now safe to copy r.px, as pn(r.pn) did not throw
411         px = r.px;
412     }
413
414     template<class Y>
415     shared_ptr( weak_ptr<Y> const & r, boost::detail::sp_nothrow_tag )
416     BOOST_NOEXCEPT : px( 0 ), pn( r.pn, boost::detail::sp_nothrow_tag() )
417     {
418         if( !pn.empty() )
419         {
420             px = r.px;
421         }
422     }
423
424     template<class Y>
425 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
426
427     shared_ptr( shared_ptr<Y> const & r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
428
429 #else
430
431     shared_ptr( shared_ptr<Y> const & r )
432
433 #endif
434     BOOST_NOEXCEPT : px( r.px ), pn( r.pn )
435     {
436         boost::detail::sp_assert_convertible< Y, T >();
437     }
438
439     // aliasing
440     template< class Y >
441     shared_ptr( shared_ptr<Y> const & r, element_type * p ) BOOST_NOEXCEPT : px( p ), pn( r.pn )
442     {
443     }
444
445 #ifndef BOOST_NO_AUTO_PTR
446
447     template<class Y>
448     explicit shared_ptr( std::auto_ptr<Y> & r ): px(r.get()), pn()
449     {
450         boost::detail::sp_assert_convertible< Y, T >();
451
452         Y * tmp = r.get();
453         pn = boost::detail::shared_count( r );
454
455         boost::detail::sp_deleter_construct( this, tmp );
456     }
457
458 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
459
460     template<class Y>
461     shared_ptr( std::auto_ptr<Y> && r ): px(r.get()), pn()
462     {
463         boost::detail::sp_assert_convertible< Y, T >();
464
465         Y * tmp = r.get();
466         pn = boost::detail::shared_count( r );
467
468         boost::detail::sp_deleter_construct( this, tmp );
469     }
470
471 #elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
472
473     template<class Ap>
474     explicit shared_ptr( Ap r, typename boost::detail::sp_enable_if_auto_ptr<Ap, int>::type = 0 ): px( r.get() ), pn()
475     {
476         typedef typename Ap::element_type Y;
477
478         boost::detail::sp_assert_convertible< Y, T >();
479
480         Y * tmp = r.get();
481         pn = boost::detail::shared_count( r );
482
483         boost::detail::sp_deleter_construct( this, tmp );
484     }
485
486 #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
487
488 #endif // BOOST_NO_AUTO_PTR
489
490 #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
491
492     template< class Y, class D >
493     shared_ptr( std::unique_ptr< Y, D > && r ): px( r.get() ), pn()
494     {
495         boost::detail::sp_assert_convertible< Y, T >();
496
497         typename std::unique_ptr< Y, D >::pointer tmp = r.get();
498         pn = boost::detail::shared_count( r );
499
500         boost::detail::sp_deleter_construct( this, tmp );
501     }
502
503 #endif
504
505     template< class Y, class D >
506     shared_ptr( boost::movelib::unique_ptr< Y, D > r ): px( r.get() ), pn()
507     {
508         boost::detail::sp_assert_convertible< Y, T >();
509
510         typename boost::movelib::unique_ptr< Y, D >::pointer tmp = r.get();
511         pn = boost::detail::shared_count( r );
512
513         boost::detail::sp_deleter_construct( this, tmp );
514     }
515
516     // assignment
517
518     shared_ptr & operator=( shared_ptr const & r ) BOOST_NOEXCEPT
519     {
520         this_type(r).swap(*this);
521         return *this;
522     }
523
524 #if !defined(BOOST_MSVC) || (BOOST_MSVC >= 1400)
525
526     template<class Y>
527     shared_ptr & operator=(shared_ptr<Y> const & r) BOOST_NOEXCEPT
528     {
529         this_type(r).swap(*this);
530         return *this;
531     }
532
533 #endif
534
535 #ifndef BOOST_NO_AUTO_PTR
536
537     template<class Y>
538     shared_ptr & operator=( std::auto_ptr<Y> & r )
539     {
540         this_type( r ).swap( *this );
541         return *this;
542     }
543
544 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
545
546     template<class Y>
547     shared_ptr & operator=( std::auto_ptr<Y> && r )
548     {
549         this_type( static_cast< std::auto_ptr<Y> && >( r ) ).swap( *this );
550         return *this;
551     }
552
553 #elif !defined( BOOST_NO_SFINAE ) && !defined( BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION )
554
555     template<class Ap>
556     typename boost::detail::sp_enable_if_auto_ptr< Ap, shared_ptr & >::type operator=( Ap r )
557     {
558         this_type( r ).swap( *this );
559         return *this;
560     }
561
562 #endif // BOOST_NO_SFINAE, BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
563
564 #endif // BOOST_NO_AUTO_PTR
565
566 #if !defined( BOOST_NO_CXX11_SMART_PTR ) && !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
567
568     template<class Y, class D>
569     shared_ptr & operator=( std::unique_ptr<Y, D> && r )
570     {
571         this_type( static_cast< std::unique_ptr<Y, D> && >( r ) ).swap(*this);
572         return *this;
573     }
574
575 #endif
576
577     template<class Y, class D>
578     shared_ptr & operator=( boost::movelib::unique_ptr<Y, D> r )
579     {
580         // this_type( static_cast< unique_ptr<Y, D> && >( r ) ).swap( *this );
581
582         boost::detail::sp_assert_convertible< Y, T >();
583
584         typename boost::movelib::unique_ptr< Y, D >::pointer p = r.get();
585
586         shared_ptr tmp;
587
588         tmp.px = p;
589         tmp.pn = boost::detail::shared_count( r );
590
591         boost::detail::sp_deleter_construct( &tmp, p );
592
593         tmp.swap( *this );
594
595         return *this;
596     }
597
598 // Move support
599
600 #if !defined( BOOST_NO_CXX11_RVALUE_REFERENCES )
601
602     shared_ptr( shared_ptr && r ) BOOST_NOEXCEPT : px( r.px ), pn()
603     {
604         pn.swap( r.pn );
605         r.px = 0;
606     }
607
608     template<class Y>
609 #if !defined( BOOST_SP_NO_SP_CONVERTIBLE )
610
611     shared_ptr( shared_ptr<Y> && r, typename boost::detail::sp_enable_if_convertible<Y,T>::type = boost::detail::sp_empty() )
612
613 #else
614
615     shared_ptr( shared_ptr<Y> && r )
616
617 #endif
618     BOOST_NOEXCEPT : px( r.px ), pn()
619     {
620         boost::detail::sp_assert_convertible< Y, T >();
621
622         pn.swap( r.pn );
623         r.px = 0;
624     }
625
626     shared_ptr & operator=( shared_ptr && r ) BOOST_NOEXCEPT
627     {
628         this_type( static_cast< shared_ptr && >( r ) ).swap( *this );
629         return *this;
630     }
631
632     template<class Y>
633     shared_ptr & operator=( shared_ptr<Y> && r ) BOOST_NOEXCEPT
634     {
635         this_type( static_cast< shared_ptr<Y> && >( r ) ).swap( *this );
636         return *this;
637     }
638
639 #endif
640
641 #if !defined( BOOST_NO_CXX11_NULLPTR )
642
643     shared_ptr & operator=( boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT // never throws
644     {
645         this_type().swap(*this);
646         return *this;
647     }
648
649 #endif
650
651     void reset() BOOST_NOEXCEPT // never throws in 1.30+
652     {
653         this_type().swap(*this);
654     }
655
656     template<class Y> void reset( Y * p ) // Y must be complete
657     {
658         BOOST_ASSERT( p == 0 || p != px ); // catch self-reset errors
659         this_type( p ).swap( *this );
660     }
661
662     template<class Y, class D> void reset( Y * p, D d )
663     {
664         this_type( p, d ).swap( *this );
665     }
666
667     template<class Y, class D, class A> void reset( Y * p, D d, A a )
668     {
669         this_type( p, d, a ).swap( *this );
670     }
671
672     template<class Y> void reset( shared_ptr<Y> const & r, element_type * p )
673     {
674         this_type( r, p ).swap( *this );
675     }
676     
677     // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
678     typename boost::detail::sp_dereference< T >::type operator* () const
679     {
680         BOOST_ASSERT( px != 0 );
681         return *px;
682     }
683     
684     // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
685     typename boost::detail::sp_member_access< T >::type operator-> () const 
686     {
687         BOOST_ASSERT( px != 0 );
688         return px;
689     }
690     
691     // never throws (but has a BOOST_ASSERT in it, so not marked with BOOST_NOEXCEPT)
692     typename boost::detail::sp_array_access< T >::type operator[] ( std::ptrdiff_t i ) const
693     {
694         BOOST_ASSERT( px != 0 );
695         BOOST_ASSERT( i >= 0 && ( i < boost::detail::sp_extent< T >::value || boost::detail::sp_extent< T >::value == 0 ) );
696
697         return static_cast< typename boost::detail::sp_array_access< T >::type >( px[ i ] );
698     }
699
700     element_type * get() const BOOST_NOEXCEPT
701     {
702         return px;
703     }
704
705 // implicit conversion to "bool"
706 #include <boost/smart_ptr/detail/operator_bool.hpp>
707
708     bool unique() const BOOST_NOEXCEPT
709     {
710         return pn.unique();
711     }
712
713     long use_count() const BOOST_NOEXCEPT
714     {
715         return pn.use_count();
716     }
717
718     void swap( shared_ptr & other ) BOOST_NOEXCEPT
719     {
720         std::swap(px, other.px);
721         pn.swap(other.pn);
722     }
723
724     template<class Y> bool owner_before( shared_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
725     {
726         return pn < rhs.pn;
727     }
728
729     template<class Y> bool owner_before( weak_ptr<Y> const & rhs ) const BOOST_NOEXCEPT
730     {
731         return pn < rhs.pn;
732     }
733
734     void * _internal_get_deleter( boost::detail::sp_typeinfo const & ti ) const BOOST_NOEXCEPT
735     {
736         return pn.get_deleter( ti );
737     }
738
739     void * _internal_get_untyped_deleter() const BOOST_NOEXCEPT
740     {
741         return pn.get_untyped_deleter();
742     }
743
744     bool _internal_equiv( shared_ptr const & r ) const BOOST_NOEXCEPT
745     {
746         return px == r.px && pn == r.pn;
747     }
748
749 // Tasteless as this may seem, making all members public allows member templates
750 // to work in the absence of member template friends. (Matthew Langston)
751
752 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
753
754 private:
755
756     template<class Y> friend class shared_ptr;
757     template<class Y> friend class weak_ptr;
758
759
760 #endif
761
762     element_type * px;                 // contained pointer
763     boost::detail::shared_count pn;    // reference counter
764
765 };  // shared_ptr
766
767 template<class T, class U> inline bool operator==(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
768 {
769     return a.get() == b.get();
770 }
771
772 template<class T, class U> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
773 {
774     return a.get() != b.get();
775 }
776
777 #if __GNUC__ == 2 && __GNUC_MINOR__ <= 96
778
779 // Resolve the ambiguity between our op!= and the one in rel_ops
780
781 template<class T> inline bool operator!=(shared_ptr<T> const & a, shared_ptr<T> const & b) BOOST_NOEXCEPT
782 {
783     return a.get() != b.get();
784 }
785
786 #endif
787
788 #if !defined( BOOST_NO_CXX11_NULLPTR )
789
790 template<class T> inline bool operator==( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
791 {
792     return p.get() == 0;
793 }
794
795 template<class T> inline bool operator==( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
796 {
797     return p.get() == 0;
798 }
799
800 template<class T> inline bool operator!=( shared_ptr<T> const & p, boost::detail::sp_nullptr_t ) BOOST_NOEXCEPT
801 {
802     return p.get() != 0;
803 }
804
805 template<class T> inline bool operator!=( boost::detail::sp_nullptr_t, shared_ptr<T> const & p ) BOOST_NOEXCEPT
806 {
807     return p.get() != 0;
808 }
809
810 #endif
811
812 template<class T, class U> inline bool operator<(shared_ptr<T> const & a, shared_ptr<U> const & b) BOOST_NOEXCEPT
813 {
814     return a.owner_before( b );
815 }
816
817 template<class T> inline void swap(shared_ptr<T> & a, shared_ptr<T> & b) BOOST_NOEXCEPT
818 {
819     a.swap(b);
820 }
821
822 template<class T, class U> shared_ptr<T> static_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
823 {
824     (void) static_cast< T* >( static_cast< U* >( 0 ) );
825
826     typedef typename shared_ptr<T>::element_type E;
827
828     E * p = static_cast< E* >( r.get() );
829     return shared_ptr<T>( r, p );
830 }
831
832 template<class T, class U> shared_ptr<T> const_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
833 {
834     (void) const_cast< T* >( static_cast< U* >( 0 ) );
835
836     typedef typename shared_ptr<T>::element_type E;
837
838     E * p = const_cast< E* >( r.get() );
839     return shared_ptr<T>( r, p );
840 }
841
842 template<class T, class U> shared_ptr<T> dynamic_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
843 {
844     (void) dynamic_cast< T* >( static_cast< U* >( 0 ) );
845
846     typedef typename shared_ptr<T>::element_type E;
847
848     E * p = dynamic_cast< E* >( r.get() );
849     return p? shared_ptr<T>( r, p ): shared_ptr<T>();
850 }
851
852 template<class T, class U> shared_ptr<T> reinterpret_pointer_cast( shared_ptr<U> const & r ) BOOST_NOEXCEPT
853 {
854     (void) reinterpret_cast< T* >( static_cast< U* >( 0 ) );
855
856     typedef typename shared_ptr<T>::element_type E;
857
858     E * p = reinterpret_cast< E* >( r.get() );
859     return shared_ptr<T>( r, p );
860 }
861
862 // get_pointer() enables boost::mem_fn to recognize shared_ptr
863
864 template<class T> inline typename shared_ptr<T>::element_type * get_pointer(shared_ptr<T> const & p) BOOST_NOEXCEPT
865 {
866     return p.get();
867 }
868
869 // operator<<
870
871 #if !defined(BOOST_NO_IOSTREAM)
872
873 #if defined(BOOST_NO_TEMPLATED_IOSTREAMS) || ( defined(__GNUC__) &&  (__GNUC__ < 3) )
874
875 template<class Y> std::ostream & operator<< (std::ostream & os, shared_ptr<Y> const & p)
876 {
877     os << p.get();
878     return os;
879 }
880
881 #else
882
883 // in STLport's no-iostreams mode no iostream symbols can be used
884 #ifndef _STLP_NO_IOSTREAMS
885
886 # if defined(BOOST_MSVC) && BOOST_WORKAROUND(BOOST_MSVC, < 1300 && __SGI_STL_PORT)
887 // MSVC6 has problems finding std::basic_ostream through the using declaration in namespace _STL
888 using std::basic_ostream;
889 template<class E, class T, class Y> basic_ostream<E, T> & operator<< (basic_ostream<E, T> & os, shared_ptr<Y> const & p)
890 # else
891 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, shared_ptr<Y> const & p)
892 # endif
893 {
894     os << p.get();
895     return os;
896 }
897
898 #endif // _STLP_NO_IOSTREAMS
899
900 #endif // __GNUC__ < 3
901
902 #endif // !defined(BOOST_NO_IOSTREAM)
903
904 // get_deleter
905
906 namespace detail
907 {
908
909 #if ( defined(__GNUC__) && BOOST_WORKAROUND(__GNUC__, < 3) ) || \
910     ( defined(__EDG_VERSION__) && BOOST_WORKAROUND(__EDG_VERSION__, <= 238) ) || \
911     ( defined(__HP_aCC) && BOOST_WORKAROUND(__HP_aCC, <= 33500) )
912
913 // g++ 2.9x doesn't allow static_cast<X const *>(void *)
914 // apparently EDG 2.38 and HP aCC A.03.35 also don't accept it
915
916 template<class D, class T> D * basic_get_deleter(shared_ptr<T> const & p)
917 {
918     void const * q = p._internal_get_deleter(BOOST_SP_TYPEID(D));
919     return const_cast<D *>(static_cast<D const *>(q));
920 }
921
922 #else
923
924 template<class D, class T> D * basic_get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
925 {
926     return static_cast<D *>( p._internal_get_deleter(BOOST_SP_TYPEID(D)) );
927 }
928
929 #endif
930
931 class esft2_deleter_wrapper
932 {
933 private:
934
935     shared_ptr<void const volatile> deleter_;
936
937 public:
938
939     esft2_deleter_wrapper()
940     {
941     }
942
943     template< class T > void set_deleter( shared_ptr<T> const & deleter )
944     {
945         deleter_ = deleter;
946     }
947
948     template<typename D> D* get_deleter() const BOOST_NOEXCEPT
949     {
950         return boost::detail::basic_get_deleter<D>( deleter_ );
951     }
952
953     template< class T> void operator()( T* )
954     {
955         BOOST_ASSERT( deleter_.use_count() <= 1 );
956         deleter_.reset();
957     }
958 };
959
960 } // namespace detail
961
962 template<class D, class T> D * get_deleter( shared_ptr<T> const & p ) BOOST_NOEXCEPT
963 {
964     D *del = boost::detail::basic_get_deleter<D>(p);
965
966     if(del == 0)
967     {
968         boost::detail::esft2_deleter_wrapper *del_wrapper = boost::detail::basic_get_deleter<boost::detail::esft2_deleter_wrapper>(p);
969 // The following get_deleter method call is fully qualified because
970 // older versions of gcc (2.95, 3.2.3) fail to compile it when written del_wrapper->get_deleter<D>()
971         if(del_wrapper) del = del_wrapper->::boost::detail::esft2_deleter_wrapper::get_deleter<D>();
972     }
973
974     return del;
975 }
976
977 // atomic access
978
979 #if !defined(BOOST_SP_NO_ATOMIC_ACCESS)
980
981 template<class T> inline bool atomic_is_lock_free( shared_ptr<T> const * /*p*/ ) BOOST_NOEXCEPT
982 {
983     return false;
984 }
985
986 template<class T> shared_ptr<T> atomic_load( shared_ptr<T> const * p )
987 {
988     boost::detail::spinlock_pool<2>::scoped_lock lock( p );
989     return *p;
990 }
991
992 template<class T> inline shared_ptr<T> atomic_load_explicit( shared_ptr<T> const * p, /*memory_order mo*/ int )
993 {
994     return atomic_load( p );
995 }
996
997 template<class T> void atomic_store( shared_ptr<T> * p, shared_ptr<T> r )
998 {
999     boost::detail::spinlock_pool<2>::scoped_lock lock( p );
1000     p->swap( r );
1001 }
1002
1003 template<class T> inline void atomic_store_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int )
1004 {
1005     atomic_store( p, r ); // std::move( r )
1006 }
1007
1008 template<class T> shared_ptr<T> atomic_exchange( shared_ptr<T> * p, shared_ptr<T> r )
1009 {
1010     boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
1011
1012     sp.lock();
1013     p->swap( r );
1014     sp.unlock();
1015
1016     return r; // return std::move( r )
1017 }
1018
1019 template<class T> shared_ptr<T> atomic_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> r, /*memory_order mo*/ int )
1020 {
1021     return atomic_exchange( p, r ); // std::move( r )
1022 }
1023
1024 template<class T> bool atomic_compare_exchange( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w )
1025 {
1026     boost::detail::spinlock & sp = boost::detail::spinlock_pool<2>::spinlock_for( p );
1027
1028     sp.lock();
1029
1030     if( p->_internal_equiv( *v ) )
1031     {
1032         p->swap( w );
1033
1034         sp.unlock();
1035
1036         return true;
1037     }
1038     else
1039     {
1040         shared_ptr<T> tmp( *p );
1041
1042         sp.unlock();
1043
1044         tmp.swap( *v );
1045         return false;
1046     }
1047 }
1048
1049 template<class T> inline bool atomic_compare_exchange_explicit( shared_ptr<T> * p, shared_ptr<T> * v, shared_ptr<T> w, /*memory_order success*/ int, /*memory_order failure*/ int )
1050 {
1051     return atomic_compare_exchange( p, v, w ); // std::move( w )
1052 }
1053
1054 #endif // !defined(BOOST_SP_NO_ATOMIC_ACCESS)
1055
1056 // hash_value
1057
1058 template< class T > struct hash;
1059
1060 template< class T > std::size_t hash_value( boost::shared_ptr<T> const & p ) BOOST_NOEXCEPT
1061 {
1062     return boost::hash< T* >()( p.get() );
1063 }
1064
1065 } // namespace boost
1066
1067 #endif  // #ifndef BOOST_SMART_PTR_SHARED_PTR_HPP_INCLUDED