intrusive_ptr.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
  2. #define BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED
  3. //
  4. // intrusive_ptr.hpp
  5. //
  6. // Copyright (c) 2001, 2002 Peter Dimov
  7. //
  8. // Distributed under the Boost Software License, Version 1.0. (See
  9. // accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. //
  12. // See http://www.boost.org/libs/smart_ptr/ for documentation.
  13. //
  14. #include <boost/smart_ptr/detail/sp_cxx20_constexpr.hpp>
  15. #include <boost/smart_ptr/detail/sp_convertible.hpp>
  16. #include <boost/smart_ptr/detail/sp_noexcept.hpp>
  17. #include <boost/assert.hpp>
  18. #include <functional> // for std::less
  19. #include <iosfwd> // for std::basic_ostream
  20. #include <cstddef>
  21. namespace boost
  22. {
  23. //
  24. // intrusive_ptr
  25. //
  26. // A smart pointer that uses intrusive reference counting.
  27. //
  28. // Relies on unqualified calls to
  29. //
  30. // void intrusive_ptr_add_ref(T * p);
  31. // void intrusive_ptr_release(T * p);
  32. //
  33. // (p != 0)
  34. //
  35. // The object is responsible for destroying itself.
  36. //
  37. template<class T> class intrusive_ptr
  38. {
  39. private:
  40. typedef intrusive_ptr this_type;
  41. public:
  42. typedef T element_type;
  43. constexpr intrusive_ptr() noexcept : px( 0 )
  44. {
  45. }
  46. BOOST_SP_CXX20_CONSTEXPR intrusive_ptr( T * p, bool add_ref = true ): px( p )
  47. {
  48. if( px != 0 && add_ref ) intrusive_ptr_add_ref( px );
  49. }
  50. template<class U>
  51. BOOST_SP_CXX20_CONSTEXPR intrusive_ptr( intrusive_ptr<U> const & rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty() )
  52. : px( rhs.get() )
  53. {
  54. if( px != 0 ) intrusive_ptr_add_ref( px );
  55. }
  56. BOOST_SP_CXX20_CONSTEXPR intrusive_ptr(intrusive_ptr const & rhs): px( rhs.px )
  57. {
  58. if( px != 0 ) intrusive_ptr_add_ref( px );
  59. }
  60. BOOST_SP_CXX20_CONSTEXPR ~intrusive_ptr()
  61. {
  62. if( px != 0 ) intrusive_ptr_release( px );
  63. }
  64. template<class U> BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr<U> const & rhs)
  65. {
  66. this_type(rhs).swap(*this);
  67. return *this;
  68. }
  69. // Move support
  70. BOOST_SP_CXX20_CONSTEXPR intrusive_ptr(intrusive_ptr && rhs) noexcept : px( rhs.px )
  71. {
  72. rhs.px = 0;
  73. }
  74. BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr && rhs) noexcept
  75. {
  76. this_type( static_cast< intrusive_ptr && >( rhs ) ).swap(*this);
  77. return *this;
  78. }
  79. template<class U> friend class intrusive_ptr;
  80. template<class U>
  81. BOOST_SP_CXX20_CONSTEXPR intrusive_ptr(intrusive_ptr<U> && rhs, typename boost::detail::sp_enable_if_convertible<U,T>::type = boost::detail::sp_empty())
  82. : px( rhs.px )
  83. {
  84. rhs.px = 0;
  85. }
  86. template<class U>
  87. BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr<U> && rhs) noexcept
  88. {
  89. this_type( static_cast< intrusive_ptr<U> && >( rhs ) ).swap(*this);
  90. return *this;
  91. }
  92. BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(intrusive_ptr const & rhs)
  93. {
  94. this_type(rhs).swap(*this);
  95. return *this;
  96. }
  97. BOOST_SP_CXX20_CONSTEXPR intrusive_ptr & operator=(T * rhs)
  98. {
  99. this_type(rhs).swap(*this);
  100. return *this;
  101. }
  102. BOOST_SP_CXX20_CONSTEXPR void reset()
  103. {
  104. this_type().swap( *this );
  105. }
  106. BOOST_SP_CXX20_CONSTEXPR void reset( T * rhs )
  107. {
  108. this_type( rhs ).swap( *this );
  109. }
  110. BOOST_SP_CXX20_CONSTEXPR void reset( T * rhs, bool add_ref )
  111. {
  112. this_type( rhs, add_ref ).swap( *this );
  113. }
  114. BOOST_SP_CXX20_CONSTEXPR T * get() const noexcept
  115. {
  116. return px;
  117. }
  118. BOOST_SP_CXX20_CONSTEXPR T * detach() noexcept
  119. {
  120. T * ret = px;
  121. px = 0;
  122. return ret;
  123. }
  124. BOOST_SP_CXX20_CONSTEXPR T & operator*() const BOOST_SP_NOEXCEPT_WITH_ASSERT
  125. {
  126. BOOST_ASSERT( px != 0 );
  127. return *px;
  128. }
  129. BOOST_SP_CXX20_CONSTEXPR T * operator->() const BOOST_SP_NOEXCEPT_WITH_ASSERT
  130. {
  131. BOOST_ASSERT( px != 0 );
  132. return px;
  133. }
  134. BOOST_SP_CXX20_CONSTEXPR explicit operator bool () const noexcept
  135. {
  136. return px != 0;
  137. }
  138. BOOST_SP_CXX20_CONSTEXPR void swap(intrusive_ptr & rhs) noexcept
  139. {
  140. T * tmp = px;
  141. px = rhs.px;
  142. rhs.px = tmp;
  143. }
  144. private:
  145. T * px;
  146. };
  147. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator==(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept
  148. {
  149. return a.get() == b.get();
  150. }
  151. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=(intrusive_ptr<T> const & a, intrusive_ptr<U> const & b) noexcept
  152. {
  153. return a.get() != b.get();
  154. }
  155. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator==(intrusive_ptr<T> const & a, U * b) noexcept
  156. {
  157. return a.get() == b;
  158. }
  159. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=(intrusive_ptr<T> const & a, U * b) noexcept
  160. {
  161. return a.get() != b;
  162. }
  163. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator==(T * a, intrusive_ptr<U> const & b) noexcept
  164. {
  165. return a == b.get();
  166. }
  167. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=(T * a, intrusive_ptr<U> const & b) noexcept
  168. {
  169. return a != b.get();
  170. }
  171. template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator==( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept
  172. {
  173. return p.get() == 0;
  174. }
  175. template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator==( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept
  176. {
  177. return p.get() == 0;
  178. }
  179. template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=( intrusive_ptr<T> const & p, std::nullptr_t ) noexcept
  180. {
  181. return p.get() != 0;
  182. }
  183. template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator!=( std::nullptr_t, intrusive_ptr<T> const & p ) noexcept
  184. {
  185. return p.get() != 0;
  186. }
  187. template<class T> BOOST_SP_CXX20_CONSTEXPR inline bool operator<(intrusive_ptr<T> const & a, intrusive_ptr<T> const & b) noexcept
  188. {
  189. return std::less<T *>()(a.get(), b.get());
  190. }
  191. template<class T> BOOST_SP_CXX20_CONSTEXPR inline void swap(intrusive_ptr<T> & lhs, intrusive_ptr<T> & rhs) noexcept
  192. {
  193. lhs.swap(rhs);
  194. }
  195. // mem_fn support
  196. template<class T> BOOST_SP_CXX20_CONSTEXPR inline T * get_pointer(intrusive_ptr<T> const & p) noexcept
  197. {
  198. return p.get();
  199. }
  200. // pointer casts
  201. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> static_pointer_cast(intrusive_ptr<U> const & p)
  202. {
  203. return static_cast<T *>(p.get());
  204. }
  205. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> const_pointer_cast(intrusive_ptr<U> const & p)
  206. {
  207. return const_cast<T *>(p.get());
  208. }
  209. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> dynamic_pointer_cast(intrusive_ptr<U> const & p)
  210. {
  211. return dynamic_cast<T *>(p.get());
  212. }
  213. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> static_pointer_cast( intrusive_ptr<U> && p ) noexcept
  214. {
  215. return intrusive_ptr<T>( static_cast<T*>( p.detach() ), false );
  216. }
  217. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> const_pointer_cast( intrusive_ptr<U> && p ) noexcept
  218. {
  219. return intrusive_ptr<T>( const_cast<T*>( p.detach() ), false );
  220. }
  221. template<class T, class U> BOOST_SP_CXX20_CONSTEXPR inline intrusive_ptr<T> dynamic_pointer_cast( intrusive_ptr<U> && p ) noexcept
  222. {
  223. T * p2 = dynamic_cast<T*>( p.get() );
  224. intrusive_ptr<T> r( p2, false );
  225. if( p2 ) p.detach();
  226. return r;
  227. }
  228. // operator<<
  229. template<class E, class T, class Y> std::basic_ostream<E, T> & operator<< (std::basic_ostream<E, T> & os, intrusive_ptr<Y> const & p)
  230. {
  231. os << p.get();
  232. return os;
  233. }
  234. // hash_value
  235. template< class T > struct hash;
  236. template< class T > std::size_t hash_value( boost::intrusive_ptr<T> const & p ) noexcept
  237. {
  238. return boost::hash< T* >()( p.get() );
  239. }
  240. } // namespace boost
  241. // std::hash
  242. namespace std
  243. {
  244. template<class T> struct hash< ::boost::intrusive_ptr<T> >
  245. {
  246. std::size_t operator()( ::boost::intrusive_ptr<T> const & p ) const noexcept
  247. {
  248. return std::hash< T* >()( p.get() );
  249. }
  250. };
  251. } // namespace std
  252. #endif // #ifndef BOOST_SMART_PTR_INTRUSIVE_PTR_HPP_INCLUDED