pointer_traits.hpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326
  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-2014. 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. #include <boost/intrusive/detail/config_begin.hpp>
  19. #include <boost/intrusive/detail/workaround.hpp>
  20. #include <boost/intrusive/pointer_rebind.hpp>
  21. #include <boost/move/detail/pointer_element.hpp>
  22. #include <boost/intrusive/detail/mpl.hpp>
  23. #include <cstddef>
  24. #if defined(BOOST_HAS_PRAGMA_ONCE)
  25. # pragma once
  26. #endif
  27. namespace boost {
  28. namespace intrusive {
  29. namespace detail {
  30. #if !defined(BOOST_MSVC) || (BOOST_MSVC > 1310)
  31. BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_pointer_to, pointer_to)
  32. BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_dynamic_cast_from, dynamic_cast_from)
  33. BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_static_cast_from, static_cast_from)
  34. BOOST_INTRUSIVE_HAS_STATIC_MEMBER_FUNC_SIGNATURE(has_member_function_callable_with_const_cast_from, const_cast_from)
  35. #else
  36. BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_pointer_to, pointer_to)
  37. BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_dynamic_cast_from, dynamic_cast_from)
  38. BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_static_cast_from, static_cast_from)
  39. BOOST_INTRUSIVE_HAS_MEMBER_FUNC_CALLED_IGNORE_SIGNATURE(has_member_function_callable_with_const_cast_from, const_cast_from)
  40. #endif
  41. BOOST_INTRUSIVE_INSTANTIATE_EVAL_DEFAULT_TYPE_TMPLT(element_type)
  42. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(difference_type)
  43. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(size_type)
  44. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(reference)
  45. BOOST_INTRUSIVE_INSTANTIATE_DEFAULT_TYPE_TMPLT(value_traits_ptr)
  46. } //namespace detail {
  47. //! pointer_traits is the implementation of C++11 std::pointer_traits class with some
  48. //! extensions like castings.
  49. //!
  50. //! pointer_traits supplies a uniform interface to certain attributes of pointer-like types.
  51. //!
  52. //! <b>Note</b>: When defining a custom family of pointers or references to be used with BI
  53. //! library, make sure the public static conversion functions accessed through
  54. //! the `pointer_traits` interface (`*_cast_from` and `pointer_to`) can
  55. //! properly convert between const and nonconst referred member types
  56. //! <b>without the use of implicit constructor calls</b>. It is suggested these
  57. //! conversions be implemented as function templates, where the template
  58. //! argument is the type of the object being converted from.
  59. template <typename Ptr>
  60. struct pointer_traits
  61. {
  62. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  63. //!The pointer type
  64. //!queried by this pointer_traits instantiation
  65. typedef Ptr pointer;
  66. //!Ptr::element_type if such a type exists; otherwise, T if Ptr is a class
  67. //!template instantiation of the form SomePointer<T, Args>, where Args is zero or
  68. //!more type arguments ; otherwise , the specialization is ill-formed.
  69. typedef unspecified_type element_type;
  70. //!Ptr::difference_type if such a type exists; otherwise,
  71. //!std::ptrdiff_t.
  72. typedef unspecified_type difference_type;
  73. //!Ptr::rebind<U> if such a type exists; otherwise, SomePointer<U, Args> if Ptr is
  74. //!a class template instantiation of the form SomePointer<T, Args>, where Args is zero or
  75. //!more type arguments ; otherwise, the instantiation of rebind is ill-formed.
  76. //!
  77. //!For portable code for C++03 and C++11, <pre>typename rebind_pointer<U>::type</pre>
  78. //!shall be used instead of rebind<U> to obtain a pointer to U.
  79. template <class U> using rebind = unspecified;
  80. //!Ptr::reference if such a type exists (non-standard extension); otherwise, element_type &
  81. //!
  82. typedef unspecified_type reference;
  83. #else
  84. typedef Ptr pointer;
  85. //
  86. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_EVAL_DEFAULT
  87. ( boost::intrusive::detail::, Ptr, element_type
  88. , boost::movelib::detail::first_param<Ptr>) element_type;
  89. //
  90. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  91. (boost::intrusive::detail::, Ptr, difference_type, std::ptrdiff_t) difference_type;
  92. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  93. ( boost::intrusive::detail::, Ptr, size_type
  94. , typename boost::move_detail::
  95. make_unsigned<difference_type>::type) size_type;
  96. typedef BOOST_INTRUSIVE_OBTAIN_TYPE_WITH_DEFAULT
  97. ( boost::intrusive::detail::, Ptr, reference
  98. , typename boost::intrusive::detail::unvoid_ref<element_type>::type) reference;
  99. //
  100. template <class U> struct rebind_pointer
  101. {
  102. typedef typename boost::intrusive::pointer_rebind<Ptr, U>::type type;
  103. };
  104. #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  105. template <class U> using rebind = typename boost::intrusive::pointer_rebind<Ptr, U>::type;
  106. #endif
  107. #endif //#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  108. //! <b>Remark</b>: If element_type is (possibly cv-qualified) void, r type is unspecified; otherwise,
  109. //! it is element_type &.
  110. //!
  111. //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling Ptr::pointer_to(reference).
  112. //! Non-standard extension: If such function does not exist, returns pointer(addressof(r));
  113. //!
  114. //! <b>Note</b>: For non-conforming compilers only the existence of a member function called
  115. //! <code>pointer_to</code> is checked.
  116. BOOST_INTRUSIVE_FORCEINLINE static pointer pointer_to(reference r) BOOST_NOEXCEPT
  117. {
  118. //Non-standard extension, it does not require Ptr::pointer_to. If not present
  119. //tries to converts &r to pointer.
  120. const bool value = boost::intrusive::detail::
  121. has_member_function_callable_with_pointer_to
  122. <Ptr, Ptr (*)(reference)>::value;
  123. boost::intrusive::detail::bool_<value> flag;
  124. return pointer_traits::priv_pointer_to(flag, r);
  125. }
  126. //! <b>Remark</b>: Non-standard extension.
  127. //!
  128. //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling the static template function
  129. //! Ptr::static_cast_from(UPpr/const UPpr &).
  130. //! If such function does not exist, returns pointer_to(static_cast<element_type&>(*uptr))
  131. //!
  132. //! <b>Note</b>: For non-conforming compilers only the existence of a member function called
  133. //! <code>static_cast_from</code> is checked.
  134. template<class UPtr>
  135. BOOST_INTRUSIVE_FORCEINLINE static pointer static_cast_from(const UPtr &uptr) BOOST_NOEXCEPT
  136. {
  137. typedef const UPtr &RefArg;
  138. const bool value = boost::intrusive::detail::
  139. has_member_function_callable_with_static_cast_from
  140. <pointer, pointer(*)(RefArg)>::value
  141. || boost::intrusive::detail::
  142. has_member_function_callable_with_static_cast_from
  143. <pointer, pointer(*)(UPtr)>::value;
  144. return pointer_traits::priv_static_cast_from(boost::intrusive::detail::bool_<value>(), uptr);
  145. }
  146. //! <b>Remark</b>: Non-standard extension.
  147. //!
  148. //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling the static template function
  149. //! Ptr::const_cast_from<UPtr>(UPpr/const UPpr &).
  150. //! If such function does not exist, returns pointer_to(const_cast<element_type&>(*uptr))
  151. //!
  152. //! <b>Note</b>: For non-conforming compilers only the existence of a member function called
  153. //! <code>const_cast_from</code> is checked.
  154. template<class UPtr>
  155. BOOST_INTRUSIVE_FORCEINLINE static pointer const_cast_from(const UPtr &uptr) BOOST_NOEXCEPT
  156. {
  157. typedef const UPtr &RefArg;
  158. const bool value = boost::intrusive::detail::
  159. has_member_function_callable_with_const_cast_from
  160. <pointer, pointer(*)(RefArg)>::value
  161. || boost::intrusive::detail::
  162. has_member_function_callable_with_const_cast_from
  163. <pointer, pointer(*)(UPtr)>::value;
  164. return pointer_traits::priv_const_cast_from(boost::intrusive::detail::bool_<value>(), uptr);
  165. }
  166. //! <b>Remark</b>: Non-standard extension.
  167. //!
  168. //! <b>Returns</b>: A dereferenceable pointer to r obtained by calling the static template function
  169. //! Ptr::dynamic_cast_from<UPtr>(UPpr/const UPpr &).
  170. //! If such function does not exist, returns pointer_to(*dynamic_cast<element_type*>(&*uptr))
  171. //!
  172. //! <b>Note</b>: For non-conforming compilers only the existence of a member function called
  173. //! <code>dynamic_cast_from</code> is checked.
  174. template<class UPtr>
  175. BOOST_INTRUSIVE_FORCEINLINE static pointer dynamic_cast_from(const UPtr &uptr) BOOST_NOEXCEPT
  176. {
  177. typedef const UPtr &RefArg;
  178. const bool value = boost::intrusive::detail::
  179. has_member_function_callable_with_dynamic_cast_from
  180. <pointer, pointer(*)(RefArg)>::value
  181. || boost::intrusive::detail::
  182. has_member_function_callable_with_dynamic_cast_from
  183. <pointer, pointer(*)(UPtr)>::value;
  184. return pointer_traits::priv_dynamic_cast_from(boost::intrusive::detail::bool_<value>(), uptr);
  185. }
  186. ///@cond
  187. private:
  188. //priv_to_raw_pointer
  189. template <class T>
  190. BOOST_INTRUSIVE_FORCEINLINE static T* to_raw_pointer(T* p) BOOST_NOEXCEPT
  191. { return p; }
  192. template <class Pointer>
  193. BOOST_INTRUSIVE_FORCEINLINE static typename pointer_traits<Pointer>::element_type*
  194. to_raw_pointer(const Pointer &p) BOOST_NOEXCEPT
  195. { return pointer_traits::to_raw_pointer(p.operator->()); }
  196. //priv_pointer_to
  197. BOOST_INTRUSIVE_FORCEINLINE static pointer priv_pointer_to(boost::intrusive::detail::true_, reference r) BOOST_NOEXCEPT
  198. { return Ptr::pointer_to(r); }
  199. BOOST_INTRUSIVE_FORCEINLINE static pointer priv_pointer_to(boost::intrusive::detail::false_, reference r) BOOST_NOEXCEPT
  200. { return pointer(boost::intrusive::detail::addressof(r)); }
  201. //priv_static_cast_from
  202. template<class UPtr>
  203. BOOST_INTRUSIVE_FORCEINLINE static pointer priv_static_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) BOOST_NOEXCEPT
  204. { return Ptr::static_cast_from(uptr); }
  205. template<class UPtr>
  206. BOOST_INTRUSIVE_FORCEINLINE static pointer priv_static_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) BOOST_NOEXCEPT
  207. { return uptr ? pointer_to(*static_cast<element_type*>(to_raw_pointer(uptr))) : pointer(); }
  208. //priv_const_cast_from
  209. template<class UPtr>
  210. BOOST_INTRUSIVE_FORCEINLINE static pointer priv_const_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) BOOST_NOEXCEPT
  211. { return Ptr::const_cast_from(uptr); }
  212. template<class UPtr>
  213. BOOST_INTRUSIVE_FORCEINLINE static pointer priv_const_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) BOOST_NOEXCEPT
  214. { return uptr ? pointer_to(const_cast<element_type&>(*uptr)) : pointer(); }
  215. //priv_dynamic_cast_from
  216. template<class UPtr>
  217. BOOST_INTRUSIVE_FORCEINLINE static pointer priv_dynamic_cast_from(boost::intrusive::detail::true_, const UPtr &uptr) BOOST_NOEXCEPT
  218. { return Ptr::dynamic_cast_from(uptr); }
  219. template<class UPtr>
  220. BOOST_INTRUSIVE_FORCEINLINE static pointer priv_dynamic_cast_from(boost::intrusive::detail::false_, const UPtr &uptr) BOOST_NOEXCEPT
  221. { return uptr ? pointer_to(dynamic_cast<element_type&>(*uptr)) : pointer(); }
  222. ///@endcond
  223. };
  224. ///@cond
  225. // Remove cv qualification from Ptr parameter to pointer_traits:
  226. template <typename Ptr>
  227. struct pointer_traits<const Ptr> : pointer_traits<Ptr> {};
  228. template <typename Ptr>
  229. struct pointer_traits<volatile Ptr> : pointer_traits<Ptr> { };
  230. template <typename Ptr>
  231. struct pointer_traits<const volatile Ptr> : pointer_traits<Ptr> { };
  232. // Remove reference from Ptr parameter to pointer_traits:
  233. template <typename Ptr>
  234. struct pointer_traits<Ptr&> : pointer_traits<Ptr> { };
  235. ///@endcond
  236. //! Specialization of pointer_traits for raw pointers
  237. //!
  238. template <typename T>
  239. struct pointer_traits<T*>
  240. {
  241. typedef T element_type;
  242. typedef T* pointer;
  243. typedef std::ptrdiff_t difference_type;
  244. typedef std::size_t size_type;
  245. #ifdef BOOST_INTRUSIVE_DOXYGEN_INVOKED
  246. typedef T & reference;
  247. //!typedef for <pre>U *</pre>
  248. //!
  249. //!For portable code for C++03 and C++11, <pre>typename rebind_pointer<U>::type</pre>
  250. //!shall be used instead of rebind<U> to obtain a pointer to U.
  251. template <class U> using rebind = U*;
  252. #else
  253. typedef typename boost::intrusive::detail::unvoid_ref<element_type>::type reference;
  254. #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
  255. template <class U> using rebind = U*;
  256. #endif
  257. #endif
  258. template <class U> struct rebind_pointer
  259. { typedef U* type; };
  260. //! <b>Returns</b>: addressof(r)
  261. //!
  262. BOOST_INTRUSIVE_FORCEINLINE static pointer pointer_to(reference r) BOOST_NOEXCEPT
  263. { return boost::intrusive::detail::addressof(r); }
  264. //! <b>Returns</b>: static_cast<pointer>(uptr)
  265. //!
  266. template<class U>
  267. BOOST_INTRUSIVE_FORCEINLINE static pointer static_cast_from(U *uptr) BOOST_NOEXCEPT
  268. { return static_cast<pointer>(uptr); }
  269. //! <b>Returns</b>: const_cast<pointer>(uptr)
  270. //!
  271. template<class U>
  272. BOOST_INTRUSIVE_FORCEINLINE static pointer const_cast_from(U *uptr) BOOST_NOEXCEPT
  273. { return const_cast<pointer>(uptr); }
  274. //! <b>Returns</b>: dynamic_cast<pointer>(uptr)
  275. //!
  276. template<class U>
  277. BOOST_INTRUSIVE_FORCEINLINE static pointer dynamic_cast_from(U *uptr) BOOST_NOEXCEPT
  278. { return dynamic_cast<pointer>(uptr); }
  279. };
  280. } //namespace container {
  281. } //namespace boost {
  282. #include <boost/intrusive/detail/config_end.hpp>
  283. #endif // ! defined(BOOST_INTRUSIVE_POINTER_TRAITS_HPP)