pointer_traits.hpp 14 KB

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