pointer_traits.hpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // (C) Copyright Pablo Halpern 2009. 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. //////////////////////////////////////////////////////////////////////////////
  8. //
  9. // (C) Copyright Ion Gaztanaga 2011-2013. Distributed under the Boost
  10. // Software License, Version 1.0. (See accompanying file
  11. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  12. //
  13. // See http://www.boost.org/libs/intrusive for documentation.
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. #ifndef BOOST_INTRUSIVE_POINTER_TRAITS_HPP
  17. #define BOOST_INTRUSIVE_POINTER_TRAITS_HPP
  18. #if (defined _MSC_VER) && (_MSC_VER >= 1200)
  19. # pragma once
  20. #endif
  21. #include <boost/intrusive/detail/config_begin.hpp>
  22. #include <boost/intrusive/detail/workaround.hpp>
  23. #include <boost/intrusive/detail/memory_util.hpp>
  24. #include <boost/type_traits/integral_constant.hpp>
  25. #include <cstddef>
  26. namespace boost {
  27. namespace intrusive {
  28. //! pointer_traits is the implementation of C++11 std::pointer_traits class with some
  29. //! extensions like castings.
  30. //!
  31. //! pointer_traits supplies a uniform interface to certain attributes of pointer-like types.
  32. template <typename Ptr>
  33. struct pointer_traits
  34. {
  35. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  36. //!The pointer type
  37. //!queried by this pointer_traits instantiation
  38. typedef Ptr pointer;
  39. //!Ptr::element_type if such a type exists; otherwise, T if Ptr is a class
  40. //!template instantiation of the form SomePointer<T, Args>, where Args is zero or
  41. //!more type arguments ; otherwise , the specialization is ill-formed.
  42. typedef unspecified_type element_type;
  43. //!Ptr::difference_type if such a type exists; otherwise,
  44. //!std::ptrdiff_t.
  45. typedef unspecified_type difference_type;
  46. //!Ptr::rebind<U> if such a type exists; otherwise, SomePointer<U, Args> if Ptr is
  47. //!a class template instantiation of the form SomePointer<T, Args>, where Args is zero or
  48. //!more type arguments ; otherwise, the instantiation of rebind is ill-formed.
  49. //!
  50. //!For portable code for C++03 and C++11, <pre>typename rebind_pointer<U>::type</pre>
  51. //!shall be used instead of rebind<U> to obtain a pointer to U.
  52. template <class U> using rebind = unspecified;
  53. //!Ptr::rebind<U> if such a type exists; otherwise, SomePointer<U, Args> if Ptr is
  54. //!a class template instantiation of the form SomePointer<T, Args>, where Args is zero or
  55. //!more type arguments ; otherwise, the instantiation of rebind is ill-formed.
  56. //!
  57. typedef element_type &reference;
  58. #else
  59. typedef Ptr pointer;
  60. //
  61. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT
  62. ( boost::intrusive::detail::, Ptr, element_type
  63. , boost::intrusive::detail::first_param<Ptr>) element_type;
  64. //
  65. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  66. (boost::intrusive::detail::, Ptr, difference_type, std::ptrdiff_t) difference_type;
  67. //
  68. typedef typename boost::intrusive::detail::unvoid_ref<element_type>::type reference;
  69. //
  70. template <class U> struct rebind_pointer
  71. {
  72. typedef typename boost::intrusive::detail::type_rebinder<Ptr, U>::type type;
  73. };
  74. #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  75. template <class U> using rebind = typename boost::intrusive::detail::type_rebinder<Ptr, U>::type;
  76. #endif
  77. #endif //#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  78. //! <b>Remark</b>: If element_type is (possibly cv-qualified) void, r type is unspecified; otherwise,
  79. //! it is element_type &.
  80. //!
  81. //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::pointer_to(r).
  82. //! Non-standard extension: If such function does not exist, returns pointer(addressof(r));
  83. static pointer pointer_to(reference r)
  84. {
  85. //Non-standard extension, it does not require Ptr::pointer_to. If not present
  86. //tries to converts &r to pointer.
  87. const bool value = boost::intrusive::detail::
  88. has_member_function_callable_with_pointer_to
  89. <Ptr, typename boost::intrusive::detail::unvoid<element_type &>::type>::value;
  90. ::boost::integral_constant<bool, value> flag;
  91. return pointer_traits::priv_pointer_to(flag, r);
  92. }
  93. //! <b>Remark</b>: Non-standard extension.
  94. //!
  95. //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::static_cast_from(r).
  96. //! If such function does not exist, returns pointer_to(static_cast<element_type&>(*uptr))
  97. template<class UPtr>
  98. static pointer static_cast_from(const UPtr &uptr)
  99. {
  100. const bool value = boost::intrusive::detail::
  101. has_member_function_callable_with_static_cast_from
  102. <Ptr, const UPtr>::value;
  103. ::boost::integral_constant<bool, value> flag;
  104. return pointer_traits::priv_static_cast_from(flag, uptr);
  105. }
  106. //! <b>Remark</b>: Non-standard extension.
  107. //!
  108. //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::const_cast_from(r).
  109. //! If such function does not exist, returns pointer_to(const_cast<element_type&>(*uptr))
  110. template<class UPtr>
  111. static pointer const_cast_from(const UPtr &uptr)
  112. {
  113. const bool value = boost::intrusive::detail::
  114. has_member_function_callable_with_const_cast_from
  115. <Ptr, const UPtr>::value;
  116. ::boost::integral_constant<bool, value> flag;
  117. return pointer_traits::priv_const_cast_from(flag, uptr);
  118. }
  119. //! <b>Remark</b>: Non-standard extension.
  120. //!
  121. //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::dynamic_cast_from(r).
  122. //! If such function does not exist, returns pointer_to(*dynamic_cast<element_type*>(&*uptr))
  123. template<class UPtr>
  124. static pointer dynamic_cast_from(const UPtr &uptr)
  125. {
  126. const bool value = boost::intrusive::detail::
  127. has_member_function_callable_with_dynamic_cast_from
  128. <Ptr, const UPtr>::value;
  129. ::boost::integral_constant<bool, value> flag;
  130. return pointer_traits::priv_dynamic_cast_from(flag, uptr);
  131. }
  132. ///@cond
  133. private:
  134. //priv_to_raw_pointer
  135. template <class T>
  136. static T* to_raw_pointer(T* p)
  137. { return p; }
  138. template <class Pointer>
  139. static typename pointer_traits<Pointer>::element_type*
  140. to_raw_pointer(const Pointer &p)
  141. { return pointer_traits::to_raw_pointer(p.operator->()); }
  142. //priv_pointer_to
  143. static pointer priv_pointer_to(boost::true_type, typename boost::intrusive::detail::unvoid<element_type>::type& r)
  144. { return Ptr::pointer_to(r); }
  145. static pointer priv_pointer_to(boost::false_type, typename boost::intrusive::detail::unvoid<element_type>::type& r)
  146. { return pointer(boost::intrusive::detail::addressof(r)); }
  147. //priv_static_cast_from
  148. template<class UPtr>
  149. static pointer priv_static_cast_from(boost::true_type, const UPtr &uptr)
  150. { return Ptr::static_cast_from(uptr); }
  151. template<class UPtr>
  152. static pointer priv_static_cast_from(boost::false_type, const UPtr &uptr)
  153. { return pointer_to(*static_cast<element_type*>(to_raw_pointer(uptr))); }
  154. //priv_const_cast_from
  155. template<class UPtr>
  156. static pointer priv_const_cast_from(boost::true_type, const UPtr &uptr)
  157. { return Ptr::const_cast_from(uptr); }
  158. template<class UPtr>
  159. static pointer priv_const_cast_from(boost::false_type, const UPtr &uptr)
  160. { return pointer_to(const_cast<element_type&>(*uptr)); }
  161. //priv_dynamic_cast_from
  162. template<class UPtr>
  163. static pointer priv_dynamic_cast_from(boost::true_type, const UPtr &uptr)
  164. { return Ptr::dynamic_cast_from(uptr); }
  165. template<class UPtr>
  166. static pointer priv_dynamic_cast_from(boost::false_type, const UPtr &uptr)
  167. { return pointer_to(*dynamic_cast<element_type*>(&*uptr)); }
  168. ///@endcond
  169. };
  170. ///@cond
  171. // Remove cv qualification from Ptr parameter to pointer_traits:
  172. template <typename Ptr>
  173. struct pointer_traits<const Ptr> : pointer_traits<Ptr> {};
  174. template <typename Ptr>
  175. struct pointer_traits<volatile Ptr> : pointer_traits<Ptr> { };
  176. template <typename Ptr>
  177. struct pointer_traits<const volatile Ptr> : pointer_traits<Ptr> { };
  178. // Remove reference from Ptr parameter to pointer_traits:
  179. template <typename Ptr>
  180. struct pointer_traits<Ptr&> : pointer_traits<Ptr> { };
  181. ///@endcond
  182. //! Specialization of pointer_traits for raw pointers
  183. //!
  184. template <typename T>
  185. struct pointer_traits<T*>
  186. {
  187. typedef T element_type;
  188. typedef T* pointer;
  189. typedef std::ptrdiff_t difference_type;
  190. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  191. typedef T & reference;
  192. //!typedef for <pre>U *</pre>
  193. //!
  194. //!For portable code for C++03 and C++11, <pre>typename rebind_pointer<U>::type</pre>
  195. //!shall be used instead of rebind<U> to obtain a pointer to U.
  196. template <class U> using rebind = U*;
  197. #else
  198. typedef typename boost::intrusive::detail::unvoid_ref<element_type>::type reference;
  199. #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  200. template <class U> using rebind = U*;
  201. #endif
  202. #endif
  203. template <class U> struct rebind_pointer
  204. { typedef U* type; };
  205. //! <b>Returns</b>: addressof(r)
  206. //!
  207. static pointer pointer_to(reference r)
  208. { return boost::intrusive::detail::addressof(r); }
  209. //! <b>Returns</b>: static_cast<pointer>(uptr)
  210. //!
  211. template<class U>
  212. static pointer static_cast_from(U *uptr)
  213. { return static_cast<pointer>(uptr); }
  214. //! <b>Returns</b>: const_cast<pointer>(uptr)
  215. //!
  216. template<class U>
  217. static pointer const_cast_from(U *uptr)
  218. { return const_cast<pointer>(uptr); }
  219. //! <b>Returns</b>: dynamic_cast<pointer>(uptr)
  220. //!
  221. template<class U>
  222. static pointer dynamic_cast_from(U *uptr)
  223. { return dynamic_cast<pointer>(uptr); }
  224. };
  225. } //namespace container {
  226. } //namespace boost {
  227. #include <boost/intrusive/detail/config_end.hpp>
  228. #endif // ! defined(BOOST_INTRUSIVE_POINTER_TRAITS_HPP)