annotate DEPENDENCIES/generic/include/boost/smart_ptr/shared_ptr.hpp @ 125:34e428693f5d vext

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