smart_ptr.hpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Ion Gaztanaga 2006. Distributed under the Boost
  4. // Software License, Version 1.0. (See accompanying file
  5. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. // See http://www.boost.org/libs/intrusive for documentation.
  8. //
  9. //////////////////////////////////////////////////////////////////////////////
  10. #ifndef BOOST_INTRUSIVE_SMART_PTR_HPP
  11. #define BOOST_INTRUSIVE_SMART_PTR_HPP
  12. #include <boost/intrusive/pointer_plus_bits.hpp>
  13. #include <boost/intrusive/pointer_traits.hpp>
  14. #include <boost/intrusive/detail/iterator.hpp>
  15. #include <boost/move/adl_move_swap.hpp>
  16. #if (defined _MSC_VER)
  17. # pragma once
  18. #endif
  19. namespace boost{
  20. namespace intrusive{
  21. namespace detail {
  22. struct static_cast_tag {};
  23. struct const_cast_tag {};
  24. struct dynamic_cast_tag {};
  25. struct reinterpret_cast_tag {};
  26. } //namespace detail {
  27. //Empty class
  28. struct empty_type{};
  29. template<class T>
  30. struct random_it
  31. : public iterator<std::random_access_iterator_tag, T, std::ptrdiff_t, T*, T&>
  32. {
  33. typedef const T* const_pointer;
  34. typedef const T& const_reference;
  35. };
  36. template<> struct random_it<void>
  37. {
  38. typedef const void * const_pointer;
  39. typedef empty_type& reference;
  40. typedef const empty_type& const_reference;
  41. typedef empty_type difference_type;
  42. typedef empty_type iterator_category;
  43. };
  44. template<> struct random_it<const void>
  45. {
  46. typedef const void * const_pointer;
  47. typedef const empty_type & reference;
  48. typedef const empty_type & const_reference;
  49. typedef empty_type difference_type;
  50. typedef empty_type iterator_category;
  51. };
  52. template<> struct random_it<volatile void>
  53. {
  54. typedef const volatile void * const_pointer;
  55. typedef empty_type& reference;
  56. typedef const empty_type& const_reference;
  57. typedef empty_type difference_type;
  58. typedef empty_type iterator_category;
  59. };
  60. template<> struct random_it<const volatile void>
  61. {
  62. typedef const volatile void * const_pointer;
  63. typedef const empty_type & reference;
  64. typedef const empty_type & const_reference;
  65. typedef empty_type difference_type;
  66. typedef empty_type iterator_category;
  67. };
  68. } //namespace intrusive {
  69. } //namespace boost {
  70. namespace boost {
  71. namespace intrusive {
  72. template <class PointedType>
  73. class smart_ptr
  74. {
  75. typedef random_it<PointedType> random_it_t;
  76. typedef smart_ptr<PointedType> self_t;
  77. typedef typename random_it_t::const_pointer const_pointer_t;
  78. typedef typename random_it_t::const_reference const_reference_t;
  79. void unspecified_bool_type_func() const {}
  80. typedef void (self_t::*unspecified_bool_type)() const;
  81. public:
  82. typedef PointedType * pointer;
  83. typedef typename random_it_t::reference reference;
  84. typedef PointedType value_type;
  85. typedef typename random_it_t::difference_type difference_type;
  86. typedef typename random_it_t::iterator_category iterator_category;
  87. PointedType *m_ptr;
  88. public: //Public Functions
  89. smart_ptr()
  90. : m_ptr(0)
  91. {}
  92. //!Constructor from other smart_ptr
  93. smart_ptr(const smart_ptr& ptr)
  94. : m_ptr(ptr.m_ptr)
  95. {}
  96. static smart_ptr pointer_to(reference r)
  97. { smart_ptr p; p.m_ptr = &r; return p; }
  98. //!Constructor from other smart_ptr. If pointers of pointee types are
  99. //!convertible, offset_ptrs will be convertibles. Never throws.
  100. template<class T2>
  101. smart_ptr(const smart_ptr<T2> &ptr)
  102. : m_ptr(ptr.m_ptr)
  103. {}
  104. pointer get() const
  105. { return m_ptr; }
  106. void set(pointer p)
  107. { m_ptr = p; }
  108. //!Pointer-like -> operator. It can return 0 pointer. Never throws.
  109. pointer operator->() const
  110. { return m_ptr; }
  111. //!Dereferencing operator, if it is a null smart_ptr behavior
  112. //! is undefined. Never throws.
  113. reference operator* () const
  114. { return *m_ptr; }
  115. //!Indexing operator. Never throws.
  116. reference operator[](std::ptrdiff_t idx) const
  117. { return m_ptr[idx]; }
  118. //!Assignment from other smart_ptr. Never throws.
  119. smart_ptr& operator= (const smart_ptr & pt)
  120. { m_ptr = pt.m_ptr; return *this; }
  121. //!Assignment from related smart_ptr. If pointers of pointee types
  122. //! are assignable, offset_ptrs will be assignable. Never throws.
  123. template <class T2>
  124. smart_ptr& operator= (const smart_ptr<T2> & pt)
  125. { m_ptr = pt.m_ptr; return *this; }
  126. //!smart_ptr + std::ptrdiff_t. Never throws.
  127. smart_ptr operator+ (std::ptrdiff_t offset) const
  128. { smart_ptr s; s.m_ptr = m_ptr + offset; return s; }
  129. //!smart_ptr - std::ptrdiff_t. Never throws.
  130. smart_ptr operator- (std::ptrdiff_t offset) const
  131. { smart_ptr s; s.m_ptr = m_ptr - offset; return s; }
  132. //!smart_ptr += std::ptrdiff_t. Never throws.
  133. smart_ptr &operator+= (std::ptrdiff_t offset)
  134. { m_ptr += offset; return *this; }
  135. //!smart_ptr -= std::ptrdiff_t. Never throws.
  136. smart_ptr &operator-= (std::ptrdiff_t offset)
  137. { m_ptr -= offset; return *this; }
  138. //!++smart_ptr. Never throws.
  139. smart_ptr& operator++ (void)
  140. { ++m_ptr; return *this; }
  141. //!smart_ptr++. Never throws.
  142. smart_ptr operator++ (int)
  143. { smart_ptr temp(*this); ++*this; return temp; }
  144. //!--smart_ptr. Never throws.
  145. smart_ptr& operator-- (void)
  146. { --m_ptr; return *this; }
  147. //!smart_ptr--. Never throws.
  148. smart_ptr operator-- (int)
  149. { smart_ptr temp(*this); --*this; return temp; }
  150. //!safe bool conversion operator. Never throws.
  151. operator unspecified_bool_type() const
  152. { return m_ptr? &self_t::unspecified_bool_type_func : 0; }
  153. //!Not operator. Not needed in theory, but improves portability.
  154. //!Never throws.
  155. bool operator! () const
  156. { return m_ptr == 0; }
  157. //!swap
  158. friend void swap(smart_ptr& x, smart_ptr& y)
  159. { boost::adl_move_swap(x.m_ptr, y.m_ptr); }
  160. };
  161. //!smart_ptr<T1> == smart_ptr<T2>. Never throws.
  162. template<class T1, class T2>
  163. inline bool operator== (const smart_ptr<T1> &pt1,
  164. const smart_ptr<T2> &pt2)
  165. { return pt1.operator->() == pt2.operator->(); }
  166. //!smart_ptr<T1> != smart_ptr<T2>. Never throws.
  167. template<class T1, class T2>
  168. inline bool operator!= (const smart_ptr<T1> &pt1,
  169. const smart_ptr<T2> &pt2)
  170. { return pt1.operator->() != pt2.operator->(); }
  171. //!smart_ptr<T1> < smart_ptr<T2>. Never throws.
  172. template<class T1, class T2>
  173. inline bool operator< (const smart_ptr<T1> &pt1,
  174. const smart_ptr<T2> &pt2)
  175. { return pt1.operator->() < pt2.operator->(); }
  176. //!smart_ptr<T1> <= smart_ptr<T2>. Never throws.
  177. template<class T1, class T2>
  178. inline bool operator<= (const smart_ptr<T1> &pt1,
  179. const smart_ptr<T2> &pt2)
  180. { return pt1.operator->() <= pt2.operator->(); }
  181. //!smart_ptr<T1> > smart_ptr<T2>. Never throws.
  182. template<class T1, class T2>
  183. inline bool operator> (const smart_ptr<T1> &pt1,
  184. const smart_ptr<T2> &pt2)
  185. { return pt1.operator->() > pt2.operator->(); }
  186. //!smart_ptr<T1> >= smart_ptr<T2>. Never throws.
  187. template<class T1, class T2>
  188. inline bool operator>= (const smart_ptr<T1> &pt1,
  189. const smart_ptr<T2> &pt2)
  190. { return pt1.operator->() >= pt2.operator->(); }
  191. //!operator<<
  192. template<class E, class T, class Y>
  193. inline std::basic_ostream<E, T> & operator<<
  194. (std::basic_ostream<E, T> & os, smart_ptr<Y> const & p)
  195. { return os << p.operator->(); }
  196. //!operator>>
  197. template<class E, class T, class Y>
  198. inline std::basic_istream<E, T> & operator>>
  199. (std::basic_istream<E, T> & os, smart_ptr<Y> & p)
  200. { Y * tmp; return os >> tmp; p = tmp; }
  201. //!std::ptrdiff_t + smart_ptr
  202. template<class T>
  203. inline smart_ptr<T> operator+(std::ptrdiff_t diff, const smart_ptr<T>& right)
  204. { return right + diff; }
  205. //!smart_ptr - smart_ptr
  206. template<class T, class T2>
  207. inline std::ptrdiff_t operator- (const smart_ptr<T> &pt, const smart_ptr<T2> &pt2)
  208. { return pt.operator->()- pt2.operator->(); }
  209. } //namespace intrusive {
  210. } //namespace boost {
  211. namespace boost{
  212. //This is to support embedding a bit in the pointer
  213. //for intrusive containers, saving space
  214. namespace intrusive {
  215. template<std::size_t Alignment>
  216. struct max_pointer_plus_bits<smart_ptr<void>, Alignment>
  217. {
  218. static const std::size_t value = max_pointer_plus_bits<void*, Alignment>::value;
  219. };
  220. template<class T, std::size_t NumBits>
  221. struct pointer_plus_bits<smart_ptr<T>, NumBits>
  222. {
  223. typedef smart_ptr<T> pointer;
  224. static pointer get_pointer(const pointer &n)
  225. {
  226. pointer p;
  227. p.set(pointer_plus_bits<T*, NumBits>::get_pointer(n.get()));
  228. return p;
  229. }
  230. static void set_pointer(pointer &n, pointer p)
  231. {
  232. T *raw_n = n.get();
  233. pointer_plus_bits<T*, NumBits>::set_pointer(raw_n, p.operator->());
  234. n.set(raw_n);
  235. }
  236. static std::size_t get_bits(const pointer &n)
  237. { return pointer_plus_bits<T*, NumBits>::get_bits(n.get()); }
  238. static void set_bits(pointer &n, std::size_t c)
  239. {
  240. T *raw_n = n.operator->();
  241. pointer_plus_bits<T*, NumBits>::set_bits(raw_n, c);
  242. n.set(raw_n);
  243. }
  244. };
  245. } //namespace intrusive
  246. } //namespace boost{
  247. #endif //#ifndef BOOST_INTRUSIVE_SMART_PTR_HPP