File indexing completed on 2025-12-15 10:08:19
0001 #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
0002 #define BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #include <boost/smart_ptr/detail/sp_convertible.hpp>
0017 #include <boost/smart_ptr/detail/sp_noexcept.hpp>
0018 #include <boost/assert.hpp>
0019
0020 #include <functional> // for std::less
0021 #include <iosfwd> // for std::basic_ostream
0022 #include <cstddef>
0023
0024 namespace boost
0025 {
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042 template<class T> class intrusive_ptr
0043 {
0044 private:
0045
0046 typedef intrusive_ptr this_type;
0047
0048 public:
0049
0050 typedef T element_type;
0051
0052 constexpr intrusive_ptr() noexcept : px( 0 )
0053 {
0054 }
0055
0056 intrusive_ptr( T * p, bool add_ref = true ): px( p )
0057 {
0058 if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
0059 }
0060
0061 template<class U>
0062 intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() )
0063 : px( rhs.get() )
0064 {
0065 if( px != 0 ) intrusive_ptr_add_ref( px );
0066 }
0067
0068 intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
0069 {
0070 if( px != 0 ) intrusive_ptr_add_ref( px );
0071 }
0072
0073 ~intrusive_ptr()
0074 {
0075 if( px != 0 ) intrusive_ptr_release( px );
0076 }
0077
0078 template<class U> intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
0079 {
0080 this_type(rhs).swap(*this);
0081 return *this;
0082 }
0083
0084
0085
0086 intrusive_ptr(intrusive_ptr && rhs) noexcept : px( rhs.px )
0087 {
0088 rhs.px = 0;
0089 }
0090
0091 intrusive_ptr & operator=(intrusive_ptr && rhs) noexcept
0092 {
0093 this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
0094 return *this;
0095 }
0096
0097 template<class U> friend class intrusive_ptr;
0098
0099 template<class U>
0100 intrusive_ptr(intrusive_ptr<U> && rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty())
0101 : px( rhs.px )
0102 {
0103 rhs.px = 0;
0104 }
0105
0106 template<class U>
0107 intrusive_ptr & operator=(intrusive_ptr<U> && rhs) noexcept
0108 {
0109 this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
0110 return *this;
0111 }
0112
0113 intrusive_ptr & operator=(intrusive_ptr const & rhs)
0114 {
0115 this_type(rhs).swap(*this);
0116 return *this;
0117 }
0118
0119 intrusive_ptr & operator=(T * rhs)
0120 {
0121 this_type(rhs).swap(*this);
0122 return *this;
0123 }
0124
0125 void reset()
0126 {
0127 this_type().swap( *this );
0128 }
0129
0130 void reset( T * rhs )
0131 {
0132 this_type( rhs ).swap( *this );
0133 }
0134
0135 void reset( T * rhs, bool add_ref )
0136 {
0137 this_type( rhs, add_ref ).swap( *this );
0138 }
0139
0140 T * get() const noexcept
0141 {
0142 return px;
0143 }
0144
0145 T * detach() noexcept
0146 {
0147 T * ret = px;
0148 px = 0;
0149 return ret;
0150 }
0151
0152 T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
0153 {
0154 BOOST_ASSERT( px != 0 );
0155 return *px;
0156 }
0157
0158 T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
0159 {
0160 BOOST_ASSERT( px != 0 );
0161 return px;
0162 }
0163
0164 explicit operator bool () const noexcept
0165 {
0166 return px != 0;
0167 }
0168
0169 void swap(intrusive_ptr & rhs) noexcept
0170 {
0171 T * tmp = px;
0172 px = rhs.px;
0173 rhs.px = tmp;
0174 }
0175
0176 private:
0177
0178 T * px;
0179 };
0180
0181 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept
0182 {
0183 return a.get() == b.get();
0184 }
0185
0186 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept
0187 {
0188 return a.get() != b.get();
0189 }
0190
0191 template<class T, class U> inline bool operator==(intrusive_ptr<T> const & a, U * b) noexcept
0192 {
0193 return a.get() == b;
0194 }
0195
0196 template<class T, class U> inline bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept
0197 {
0198 return a.get() != b;
0199 }
0200
0201 template<class T, class U> inline bool operator==(T * a, intrusive_ptr<U> const & b) noexcept
0202 {
0203 return a == b.get();
0204 }
0205
0206 template<class T, class U> inline bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept
0207 {
0208 return a != b.get();
0209 }
0210
0211 template<class T> inline bool operator==( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept
0212 {
0213 return p.get() == 0;
0214 }
0215
0216 template<class T> inline bool operator==( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept
0217 {
0218 return p.get() == 0;
0219 }
0220
0221 template<class T> inline bool operator!=( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept
0222 {
0223 return p.get() != 0;
0224 }
0225
0226 template<class T> inline bool operator!=( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept
0227 {
0228 return p.get() != 0;
0229 }
0230
0231 template<class T> inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept
0232 {
0233 return std::less<T *>()(a.get(), b.get());
0234 }
0235
0236 template<class T> void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept
0237 {
0238 lhs.swap(rhs);
0239 }
0240
0241
0242
0243 template<class T> T * get_pointer(intrusive_ptr<T> const & p) noexcept
0244 {
0245 return p.get();
0246 }
0247
0248
0249
0250 template<class T, class U> intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
0251 {
0252 return static_cast<T *>(p.get());
0253 }
0254
0255 template<class T, class U> intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
0256 {
0257 return const_cast<T *>(p.get());
0258 }
0259
0260 template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
0261 {
0262 return dynamic_cast<T *>(p.get());
0263 }
0264
0265 template<class T, class U> intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) noexcept
0266 {
0267 return intrusive_ptr<T>( static_cast<T*>( p.detach() ), false );
0268 }
0269
0270 template<class T, class U> intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) noexcept
0271 {
0272 return intrusive_ptr<T>( const_cast<T*>( p.detach() ), false );
0273 }
0274
0275 template<class T, class U> intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) noexcept
0276 {
0277 T * p2 = dynamic_cast<T*>( p.get() );
0278
0279 intrusive_ptr<T> r( p2, false );
0280
0281 if( p2 ) p.detach();
0282
0283 return r;
0284 }
0285
0286
0287
0288 template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
0289 {
0290 os << p.get();
0291 return os;
0292 }
0293
0294
0295
0296 template< class T > struct hash;
0297
0298 template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p ) noexcept
0299 {
0300 return boost::hash< T* >()( p.get() );
0301 }
0302
0303 }
0304
0305
0306
0307 namespace std
0308 {
0309
0310 template<class T> struct hash< ::boost::intrusive_ptr<T> >
0311 {
0312 std::size_t operator()( ::boost::intrusive_ptr<T> const & p ) const noexcept
0313 {
0314 return std::hash< T* >()( p.get() );
0315 }
0316 };
0317
0318 }
0319
0320 #endif