1 // -*- C++ -*- 2 //===----------------------------------------------------------------------===// 3 // 4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5 // See https://llvm.org/LICENSE.txt for license information. 6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef _LIBCPP___MEMORY_POINTER_TRAITS_H 11 #define _LIBCPP___MEMORY_POINTER_TRAITS_H 12 13 #include <__config> 14 #include <__memory/addressof.h> 15 #include <__type_traits/conditional.h> 16 #include <__type_traits/conjunction.h> 17 #include <__type_traits/decay.h> 18 #include <__type_traits/is_class.h> 19 #include <__type_traits/is_function.h> 20 #include <__type_traits/is_void.h> 21 #include <__type_traits/void_t.h> 22 #include <__utility/declval.h> 23 #include <__utility/forward.h> 24 #include <cstddef> 25 26 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 27 # pragma GCC system_header 28 #endif 29 30 _LIBCPP_PUSH_MACROS 31 #include <__undef_macros> 32 33 _LIBCPP_BEGIN_NAMESPACE_STD 34 35 // clang-format off 36 #define _LIBCPP_CLASS_TRAITS_HAS_XXX(NAME, PROPERTY) \ 37 template <class _Tp, class = void> \ 38 struct NAME : false_type {}; \ 39 template <class _Tp> \ 40 struct NAME<_Tp, __void_t<typename _Tp::PROPERTY> > : true_type {} 41 // clang-format on 42 43 _LIBCPP_CLASS_TRAITS_HAS_XXX(__has_pointer, pointer); 44 _LIBCPP_CLASS_TRAITS_HAS_XXX(__has_element_type, element_type); 45 46 template <class _Ptr, bool = __has_element_type<_Ptr>::value> 47 struct __pointer_traits_element_type {}; 48 49 template <class _Ptr> 50 struct __pointer_traits_element_type<_Ptr, true> { 51 typedef _LIBCPP_NODEBUG typename _Ptr::element_type type; 52 }; 53 54 template <template <class, class...> class _Sp, class _Tp, class... _Args> 55 struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, true> { 56 typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::element_type type; 57 }; 58 59 template <template <class, class...> class _Sp, class _Tp, class... _Args> 60 struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, false> { 61 typedef _LIBCPP_NODEBUG _Tp type; 62 }; 63 64 template <class _Tp, class = void> 65 struct __has_difference_type : false_type {}; 66 67 template <class _Tp> 68 struct __has_difference_type<_Tp, __void_t<typename _Tp::difference_type> > : true_type {}; 69 70 template <class _Ptr, bool = __has_difference_type<_Ptr>::value> 71 struct __pointer_traits_difference_type { 72 typedef _LIBCPP_NODEBUG ptrdiff_t type; 73 }; 74 75 template <class _Ptr> 76 struct __pointer_traits_difference_type<_Ptr, true> { 77 typedef _LIBCPP_NODEBUG typename _Ptr::difference_type type; 78 }; 79 80 template <class _Tp, class _Up> 81 struct __has_rebind { 82 private: 83 template <class _Xp> 84 static false_type __test(...); 85 _LIBCPP_SUPPRESS_DEPRECATED_PUSH 86 template <class _Xp> 87 static true_type __test(typename _Xp::template rebind<_Up>* = 0); 88 _LIBCPP_SUPPRESS_DEPRECATED_POP 89 90 public: 91 static const bool value = decltype(__test<_Tp>(0))::value; 92 }; 93 94 template <class _Tp, class _Up, bool = __has_rebind<_Tp, _Up>::value> 95 struct __pointer_traits_rebind { 96 #ifndef _LIBCPP_CXX03_LANG 97 typedef _LIBCPP_NODEBUG typename _Tp::template rebind<_Up> type; 98 #else 99 typedef _LIBCPP_NODEBUG typename _Tp::template rebind<_Up>::other type; 100 #endif 101 }; 102 103 template <template <class, class...> class _Sp, class _Tp, class... _Args, class _Up> 104 struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, true> { 105 #ifndef _LIBCPP_CXX03_LANG 106 typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::template rebind<_Up> type; 107 #else 108 typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::template rebind<_Up>::other type; 109 #endif 110 }; 111 112 template <template <class, class...> class _Sp, class _Tp, class... _Args, class _Up> 113 struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false> { 114 typedef _Sp<_Up, _Args...> type; 115 }; 116 117 template <class _Ptr, class = void> 118 struct __pointer_traits_impl {}; 119 120 template <class _Ptr> 121 struct __pointer_traits_impl<_Ptr, __void_t<typename __pointer_traits_element_type<_Ptr>::type> > { 122 typedef _Ptr pointer; 123 typedef typename __pointer_traits_element_type<pointer>::type element_type; 124 typedef typename __pointer_traits_difference_type<pointer>::type difference_type; 125 126 #ifndef _LIBCPP_CXX03_LANG 127 template <class _Up> 128 using rebind = typename __pointer_traits_rebind<pointer, _Up>::type; 129 #else 130 template <class _Up> 131 struct rebind { 132 typedef typename __pointer_traits_rebind<pointer, _Up>::type other; 133 }; 134 #endif // _LIBCPP_CXX03_LANG 135 136 private: 137 struct __nat {}; 138 139 public: 140 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer 141 pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) { 142 return pointer::pointer_to(__r); 143 } 144 }; 145 146 template <class _Ptr> 147 struct _LIBCPP_TEMPLATE_VIS pointer_traits : __pointer_traits_impl<_Ptr> {}; 148 149 template <class _Tp> 150 struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*> { 151 typedef _Tp* pointer; 152 typedef _Tp element_type; 153 typedef ptrdiff_t difference_type; 154 155 #ifndef _LIBCPP_CXX03_LANG 156 template <class _Up> 157 using rebind = _Up*; 158 #else 159 template <class _Up> 160 struct rebind { 161 typedef _Up* other; 162 }; 163 #endif 164 165 private: 166 struct __nat {}; 167 168 public: 169 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer 170 pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) _NOEXCEPT { 171 return std::addressof(__r); 172 } 173 }; 174 175 #ifndef _LIBCPP_CXX03_LANG 176 template <class _From, class _To> 177 using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>; 178 #else 179 template <class _From, class _To> 180 using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>::other; 181 #endif 182 183 // to_address 184 185 template <class _Pointer, class = void> 186 struct __to_address_helper; 187 188 template <class _Tp> 189 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __to_address(_Tp* __p) _NOEXCEPT { 190 static_assert(!is_function<_Tp>::value, "_Tp is a function type"); 191 return __p; 192 } 193 194 template <class _Pointer, class = void> 195 struct _HasToAddress : false_type {}; 196 197 template <class _Pointer> 198 struct _HasToAddress<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) > 199 : true_type {}; 200 201 template <class _Pointer, class = void> 202 struct _HasArrow : false_type {}; 203 204 template <class _Pointer> 205 struct _HasArrow<_Pointer, decltype((void)std::declval<const _Pointer&>().operator->()) > : true_type {}; 206 207 template <class _Pointer> 208 struct _IsFancyPointer { 209 static const bool value = _HasArrow<_Pointer>::value || _HasToAddress<_Pointer>::value; 210 }; 211 212 // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers 213 template <class _Pointer, __enable_if_t< _And<is_class<_Pointer>, _IsFancyPointer<_Pointer> >::value, int> = 0> 214 _LIBCPP_HIDE_FROM_ABI 215 _LIBCPP_CONSTEXPR __decay_t<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))> 216 __to_address(const _Pointer& __p) _NOEXCEPT { 217 return __to_address_helper<_Pointer>::__call(__p); 218 } 219 220 template <class _Pointer, class> 221 struct __to_address_helper { 222 _LIBCPP_HIDE_FROM_ABI 223 _LIBCPP_CONSTEXPR static decltype(std::__to_address(std::declval<const _Pointer&>().operator->())) 224 __call(const _Pointer& __p) _NOEXCEPT { 225 return std::__to_address(__p.operator->()); 226 } 227 }; 228 229 template <class _Pointer> 230 struct __to_address_helper<_Pointer, 231 decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))> { 232 _LIBCPP_HIDE_FROM_ABI 233 _LIBCPP_CONSTEXPR static decltype(pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) 234 __call(const _Pointer& __p) _NOEXCEPT { 235 return pointer_traits<_Pointer>::to_address(__p); 236 } 237 }; 238 239 #if _LIBCPP_STD_VER >= 20 240 template <class _Tp> 241 inline _LIBCPP_HIDE_FROM_ABI constexpr auto to_address(_Tp* __p) noexcept { 242 return std::__to_address(__p); 243 } 244 245 template <class _Pointer> 246 inline _LIBCPP_HIDE_FROM_ABI constexpr auto 247 to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p)) { 248 return std::__to_address(__p); 249 } 250 #endif 251 252 #if _LIBCPP_STD_VER >= 23 253 254 template <class _Tp> 255 struct __pointer_of {}; 256 257 template <class _Tp> 258 requires(__has_pointer<_Tp>::value) 259 struct __pointer_of<_Tp> { 260 using type = typename _Tp::pointer; 261 }; 262 263 template <class _Tp> 264 requires(!__has_pointer<_Tp>::value && __has_element_type<_Tp>::value) 265 struct __pointer_of<_Tp> { 266 using type = typename _Tp::element_type*; 267 }; 268 269 template <class _Tp> 270 requires(!__has_pointer<_Tp>::value && !__has_element_type<_Tp>::value && 271 __has_element_type<pointer_traits<_Tp>>::value) 272 struct __pointer_of<_Tp> { 273 using type = typename pointer_traits<_Tp>::element_type*; 274 }; 275 276 template <typename _Tp> 277 using __pointer_of_t = typename __pointer_of<_Tp>::type; 278 279 template <class _Tp, class _Up> 280 struct __pointer_of_or { 281 using type _LIBCPP_NODEBUG = _Up; 282 }; 283 284 template <class _Tp, class _Up> 285 requires requires { typename __pointer_of_t<_Tp>; } 286 struct __pointer_of_or<_Tp, _Up> { 287 using type _LIBCPP_NODEBUG = __pointer_of_t<_Tp>; 288 }; 289 290 template <typename _Tp, typename _Up> 291 using __pointer_of_or_t = typename __pointer_of_or<_Tp, _Up>::type; 292 293 template <class _Smart> 294 concept __resettable_smart_pointer = requires(_Smart __s) { __s.reset(); }; 295 296 template <class _Smart, class _Pointer, class... _Args> 297 concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p, _Args... __args) { 298 __s.reset(static_cast<__pointer_of_or_t<_Smart, _Pointer>>(__p), std::forward<_Args>(__args)...); 299 }; 300 301 #endif 302 303 _LIBCPP_END_NAMESPACE_STD 304 305 _LIBCPP_POP_MACROS 306 307 #endif // _LIBCPP___MEMORY_POINTER_TRAITS_H 308