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