ptr_traits.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. // Pointer Traits -*- C++ -*-
  2. // Copyright (C) 2011-2018 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. namespace std _GLIBCXX_VISIBILITY(default)
  29. {
  30. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  31. class __undefined;
  32. // Given Template<T, ...> return T, otherwise invalid.
  33. template<typename _Tp>
  34. struct __get_first_arg
  35. { using type = __undefined; };
  36. template<template<typename, typename...> class _Template, typename _Tp,
  37. typename... _Types>
  38. struct __get_first_arg<_Template<_Tp, _Types...>>
  39. { using type = _Tp; };
  40. template<typename _Tp>
  41. using __get_first_arg_t = typename __get_first_arg<_Tp>::type;
  42. // Given Template<T, ...> and U return Template<U, ...>, otherwise invalid.
  43. template<typename _Tp, typename _Up>
  44. struct __replace_first_arg
  45. { };
  46. template<template<typename, typename...> class _Template, typename _Up,
  47. typename _Tp, typename... _Types>
  48. struct __replace_first_arg<_Template<_Tp, _Types...>, _Up>
  49. { using type = _Template<_Up, _Types...>; };
  50. template<typename _Tp, typename _Up>
  51. using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type;
  52. template<typename _Tp>
  53. using __make_not_void
  54. = typename conditional<is_void<_Tp>::value, __undefined, _Tp>::type;
  55. /**
  56. * @brief Uniform interface to all pointer-like types
  57. * @ingroup pointer_abstractions
  58. */
  59. template<typename _Ptr>
  60. struct pointer_traits
  61. {
  62. private:
  63. template<typename _Tp>
  64. using __element_type = typename _Tp::element_type;
  65. template<typename _Tp>
  66. using __difference_type = typename _Tp::difference_type;
  67. template<typename _Tp, typename _Up, typename = void>
  68. struct __rebind : __replace_first_arg<_Tp, _Up> { };
  69. template<typename _Tp, typename _Up>
  70. struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>>
  71. { using type = typename _Tp::template rebind<_Up>; };
  72. public:
  73. /// The pointer type.
  74. using pointer = _Ptr;
  75. /// The type pointed to.
  76. using element_type
  77. = __detected_or_t<__get_first_arg_t<_Ptr>, __element_type, _Ptr>;
  78. /// The type used to represent the difference between two pointers.
  79. using difference_type
  80. = __detected_or_t<ptrdiff_t, __difference_type, _Ptr>;
  81. /// A pointer to a different type.
  82. template<typename _Up>
  83. using rebind = typename __rebind<_Ptr, _Up>::type;
  84. static _Ptr
  85. pointer_to(__make_not_void<element_type>& __e)
  86. { return _Ptr::pointer_to(__e); }
  87. static_assert(!is_same<element_type, __undefined>::value,
  88. "pointer type defines element_type or is like SomePointer<T, Args>");
  89. };
  90. /**
  91. * @brief Partial specialization for built-in pointers.
  92. * @ingroup pointer_abstractions
  93. */
  94. template<typename _Tp>
  95. struct pointer_traits<_Tp*>
  96. {
  97. /// The pointer type
  98. typedef _Tp* pointer;
  99. /// The type pointed to
  100. typedef _Tp element_type;
  101. /// Type used to represent the difference between two pointers
  102. typedef ptrdiff_t difference_type;
  103. template<typename _Up>
  104. using rebind = _Up*;
  105. /**
  106. * @brief Obtain a pointer to an object
  107. * @param __r A reference to an object of type @c element_type
  108. * @return @c addressof(__r)
  109. */
  110. static pointer
  111. pointer_to(__make_not_void<element_type>& __r) noexcept
  112. { return std::addressof(__r); }
  113. };
  114. /// Convenience alias for rebinding pointers.
  115. template<typename _Ptr, typename _Tp>
  116. using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>;
  117. template<typename _Tp>
  118. constexpr _Tp*
  119. __to_address(_Tp* __ptr) noexcept
  120. {
  121. static_assert(!std::is_function<_Tp>::value, "not a function pointer");
  122. return __ptr;
  123. }
  124. #if __cplusplus <= 201703L
  125. template<typename _Ptr>
  126. constexpr typename std::pointer_traits<_Ptr>::element_type*
  127. __to_address(const _Ptr& __ptr)
  128. { return std::__to_address(__ptr.operator->()); }
  129. #else
  130. template<typename _Ptr>
  131. constexpr auto
  132. __to_address(const _Ptr& __ptr) noexcept
  133. -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr))
  134. { return std::pointer_traits<_Ptr>::to_address(__ptr); }
  135. template<typename _Ptr, typename... _None>
  136. constexpr auto
  137. __to_address(const _Ptr& __ptr, _None...) noexcept
  138. { return std::__to_address(__ptr.operator->()); }
  139. /**
  140. * @brief Obtain address referenced by a pointer to an object
  141. * @param __ptr A pointer to an object
  142. * @return @c __ptr
  143. * @ingroup pointer_abstractions
  144. */
  145. template<typename _Tp>
  146. constexpr _Tp*
  147. to_address(_Tp* __ptr) noexcept
  148. { return std::__to_address(__ptr); }
  149. /**
  150. * @brief Obtain address referenced by a pointer to an object
  151. * @param __ptr A pointer to an object
  152. * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is
  153. well-formed, otherwise @c to_address(__ptr.operator->())
  154. * @ingroup pointer_abstractions
  155. */
  156. template<typename _Ptr>
  157. constexpr auto
  158. to_address(const _Ptr& __ptr) noexcept
  159. { return std::__to_address(__ptr); }
  160. #endif // C++2a
  161. _GLIBCXX_END_NAMESPACE_VERSION
  162. } // namespace std
  163. #endif
  164. #endif