ptr_traits.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // Pointer Traits -*- C++ -*-
  2. // Copyright (C) 2011-2022 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /** @file bits/ptr_traits.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{memory}
  23. */
  24. #ifndef _PTR_TRAITS_H
  25. #define _PTR_TRAITS_H 1
  26. #if __cplusplus >= 201103L
  27. #include <bits/move.h>
  28. #if __cplusplus > 201703L
  29. #include <concepts>
  30. # ifndef __cpp_lib_constexpr_memory
  31. // Defined to a newer value in bits/unique_ptr.h for C++23
  32. # define __cpp_lib_constexpr_memory 201811L
  33. # endif
  34. namespace __gnu_debug { struct _Safe_iterator_base; }
  35. #endif
  36. namespace std _GLIBCXX_VISIBILITY(default)
  37. {
  38. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  39. class __undefined;
  40. // For a specialization `SomeTemplate<T, Types...>` the member `type` is T,
  41. // otherwise `type` is `__undefined`.
  42. template<typename _Tp>
  43. struct __get_first_arg
  44. { using type = __undefined; };
  45. template<template<typename, typename...> class _SomeTemplate, typename _Tp,
  46. typename... _Types>
  47. struct __get_first_arg<_SomeTemplate<_Tp, _Types...>>
  48. { using type = _Tp; };
  49. // For a specialization `SomeTemplate<T, Args...>` and a type `U` the member
  50. // `type` is `SomeTemplate<U, Args...>`, otherwise there is no member `type`.
  51. template<typename _Tp, typename _Up>
  52. struct __replace_first_arg
  53. { };
  54. template<template<typename, typename...> class _SomeTemplate, typename _Up,
  55. typename _Tp, typename... _Types>
  56. struct __replace_first_arg<_SomeTemplate<_Tp, _Types...>, _Up>
  57. { using type = _SomeTemplate<_Up, _Types...>; };
  58. #if __cpp_concepts
  59. // When concepts are supported detection of _Ptr::element_type is done
  60. // by a requires-clause, so __ptr_traits_elem_t only needs to do this:
  61. template<typename _Ptr>
  62. using __ptr_traits_elem_t = typename __get_first_arg<_Ptr>::type;
  63. #else
  64. // Detect the element type of a pointer-like type.
  65. template<typename _Ptr, typename = void>
  66. struct __ptr_traits_elem : __get_first_arg<_Ptr>
  67. { };
  68. // Use _Ptr::element_type if is a valid type.
  69. template<typename _Ptr>
  70. struct __ptr_traits_elem<_Ptr, __void_t<typename _Ptr::element_type>>
  71. { using type = typename _Ptr::element_type; };
  72. template<typename _Ptr>
  73. using __ptr_traits_elem_t = typename __ptr_traits_elem<_Ptr>::type;
  74. #endif
  75. // Define pointer_traits<P>::pointer_to.
  76. template<typename _Ptr, typename _Elt, bool = is_void<_Elt>::value>
  77. struct __ptr_traits_ptr_to
  78. {
  79. using pointer = _Ptr;
  80. using element_type = _Elt;
  81. /**
  82. * @brief Obtain a pointer to an object
  83. * @param __r A reference to an object of type `element_type`
  84. * @return `pointer::pointer_to(__e)`
  85. * @pre `pointer::pointer_to(__e)` is a valid expression.
  86. */
  87. static pointer
  88. pointer_to(element_type& __e)
  89. #if __cpp_lib_concepts
  90. requires requires {
  91. { pointer::pointer_to(__e) } -> convertible_to<pointer>;
  92. }
  93. #endif
  94. { return pointer::pointer_to(__e); }
  95. };
  96. // Do not define pointer_traits<P>::pointer_to if element type is void.
  97. template<typename _Ptr, typename _Elt>
  98. struct __ptr_traits_ptr_to<_Ptr, _Elt, true>
  99. { };
  100. // Partial specialization defining pointer_traits<T*>::pointer_to(T&).
  101. template<typename _Tp>
  102. struct __ptr_traits_ptr_to<_Tp*, _Tp, false>
  103. {
  104. using pointer = _Tp*;
  105. using element_type = _Tp;
  106. /**
  107. * @brief Obtain a pointer to an object
  108. * @param __r A reference to an object of type `element_type`
  109. * @return `addressof(__r)`
  110. */
  111. static _GLIBCXX20_CONSTEXPR pointer
  112. pointer_to(element_type& __r) noexcept
  113. { return std::addressof(__r); }
  114. };
  115. template<typename _Ptr, typename _Elt>
  116. struct __ptr_traits_impl : __ptr_traits_ptr_to<_Ptr, _Elt>
  117. {
  118. private:
  119. template<typename _Tp, typename = void>
  120. struct __difference { using type = ptrdiff_t; };
  121. template<typename _Tp>
  122. #if __cpp_concepts
  123. requires requires { typename _Tp::difference_type; }
  124. struct __difference<_Tp>
  125. #else
  126. struct __difference<_Tp, __void_t<typename _Tp::difference_type>>
  127. #endif
  128. { using type = typename _Tp::difference_type; };
  129. template<typename _Tp, typename _Up, typename = void>
  130. struct __rebind : __replace_first_arg<_Tp, _Up> { };
  131. template<typename _Tp, typename _Up>
  132. #if __cpp_concepts
  133. requires requires { typename _Tp::template rebind<_Up>; }
  134. struct __rebind<_Tp, _Up>
  135. #else
  136. struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>>
  137. #endif
  138. { using type = typename _Tp::template rebind<_Up>; };
  139. public:
  140. /// The pointer type.
  141. using pointer = _Ptr;
  142. /// The type pointed to.
  143. using element_type = _Elt;
  144. /// The type used to represent the difference between two pointers.
  145. using difference_type = typename __difference<_Ptr>::type;
  146. /// A pointer to a different type.
  147. template<typename _Up>
  148. using rebind = typename __rebind<_Ptr, _Up>::type;
  149. };
  150. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  151. // 3545. std::pointer_traits should be SFINAE-friendly
  152. template<typename _Ptr>
  153. struct __ptr_traits_impl<_Ptr, __undefined>
  154. { };
  155. /**
  156. * @brief Uniform interface to all pointer-like types
  157. * @ingroup pointer_abstractions
  158. * @since C++11
  159. */
  160. template<typename _Ptr>
  161. struct pointer_traits : __ptr_traits_impl<_Ptr, __ptr_traits_elem_t<_Ptr>>
  162. { };
  163. #if __cpp_concepts
  164. template<typename _Ptr> requires requires { typename _Ptr::element_type; }
  165. struct pointer_traits<_Ptr>
  166. : __ptr_traits_impl<_Ptr, typename _Ptr::element_type>
  167. { };
  168. #endif
  169. /**
  170. * @brief Partial specialization for built-in pointers.
  171. * @ingroup pointer_abstractions
  172. * @since C++11
  173. */
  174. template<typename _Tp>
  175. struct pointer_traits<_Tp*> : __ptr_traits_ptr_to<_Tp*, _Tp>
  176. {
  177. /// The pointer type
  178. typedef _Tp* pointer;
  179. /// The type pointed to
  180. typedef _Tp element_type;
  181. /// Type used to represent the difference between two pointers
  182. typedef ptrdiff_t difference_type;
  183. /// A pointer to a different type.
  184. template<typename _Up> using rebind = _Up*;
  185. };
  186. /// Convenience alias for rebinding pointers.
  187. template<typename _Ptr, typename _Tp>
  188. using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>;
  189. template<typename _Tp>
  190. constexpr _Tp*
  191. __to_address(_Tp* __ptr) noexcept
  192. {
  193. static_assert(!std::is_function<_Tp>::value, "not a function pointer");
  194. return __ptr;
  195. }
  196. #if __cplusplus <= 201703L
  197. template<typename _Ptr>
  198. constexpr typename std::pointer_traits<_Ptr>::element_type*
  199. __to_address(const _Ptr& __ptr)
  200. { return std::__to_address(__ptr.operator->()); }
  201. #else
  202. template<typename _Ptr>
  203. constexpr auto
  204. __to_address(const _Ptr& __ptr) noexcept
  205. -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr))
  206. { return std::pointer_traits<_Ptr>::to_address(__ptr); }
  207. template<typename _Ptr, typename... _None>
  208. constexpr auto
  209. __to_address(const _Ptr& __ptr, _None...) noexcept
  210. {
  211. if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>)
  212. return std::__to_address(__ptr.base().operator->());
  213. else
  214. return std::__to_address(__ptr.operator->());
  215. }
  216. #define __cpp_lib_to_address 201711L
  217. /**
  218. * @brief Obtain address referenced by a pointer to an object
  219. * @param __ptr A pointer to an object
  220. * @return @c __ptr
  221. * @ingroup pointer_abstractions
  222. */
  223. template<typename _Tp>
  224. constexpr _Tp*
  225. to_address(_Tp* __ptr) noexcept
  226. { return std::__to_address(__ptr); }
  227. /**
  228. * @brief Obtain address referenced by a pointer to an object
  229. * @param __ptr A pointer to an object
  230. * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is
  231. well-formed, otherwise @c to_address(__ptr.operator->())
  232. * @ingroup pointer_abstractions
  233. */
  234. template<typename _Ptr>
  235. constexpr auto
  236. to_address(const _Ptr& __ptr) noexcept
  237. { return std::__to_address(__ptr); }
  238. #endif // C++2a
  239. _GLIBCXX_END_NAMESPACE_VERSION
  240. } // namespace std
  241. #endif
  242. #endif