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 <cstddef> 24 25 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) 26 # pragma GCC system_header 27 #endif 28 29 _LIBCPP_BEGIN_NAMESPACE_STD 30 31 template <class _Tp, class = void> 32 struct __has_element_type : false_type {}; 33 34 template <class _Tp> 35 struct __has_element_type<_Tp, __void_t<typename _Tp::element_type> > : true_type {}; 36 37 template <class _Ptr, bool = __has_element_type<_Ptr>::value> 38 struct __pointer_traits_element_type {}; 39 40 template <class _Ptr> 41 struct __pointer_traits_element_type<_Ptr, true> 42 { 43 typedef _LIBCPP_NODEBUG typename _Ptr::element_type type; 44 }; 45 46 template <template <class, class...> class _Sp, class _Tp, class ..._Args> 47 struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, true> 48 { 49 typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::element_type type; 50 }; 51 52 template <template <class, class...> class _Sp, class _Tp, class ..._Args> 53 struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, false> 54 { 55 typedef _LIBCPP_NODEBUG _Tp type; 56 }; 57 58 template <class _Tp, class = void> 59 struct __has_difference_type : false_type {}; 60 61 template <class _Tp> 62 struct __has_difference_type<_Tp, __void_t<typename _Tp::difference_type> > : true_type {}; 63 64 template <class _Ptr, bool = __has_difference_type<_Ptr>::value> 65 struct __pointer_traits_difference_type 66 { 67 typedef _LIBCPP_NODEBUG ptrdiff_t type; 68 }; 69 70 template <class _Ptr> 71 struct __pointer_traits_difference_type<_Ptr, true> 72 { 73 typedef _LIBCPP_NODEBUG typename _Ptr::difference_type type; 74 }; 75 76 template <class _Tp, class _Up> 77 struct __has_rebind 78 { 79 private: 80 template <class _Xp> static false_type __test(...); 81 _LIBCPP_SUPPRESS_DEPRECATED_PUSH 82 template <class _Xp> static true_type __test(typename _Xp::template rebind<_Up>* = 0); 83 _LIBCPP_SUPPRESS_DEPRECATED_POP 84 public: 85 static const bool value = decltype(__test<_Tp>(0))::value; 86 }; 87 88 template <class _Tp, class _Up, bool = __has_rebind<_Tp, _Up>::value> 89 struct __pointer_traits_rebind 90 { 91 #ifndef _LIBCPP_CXX03_LANG 92 typedef _LIBCPP_NODEBUG typename _Tp::template rebind<_Up> type; 93 #else 94 typedef _LIBCPP_NODEBUG typename _Tp::template rebind<_Up>::other type; 95 #endif 96 }; 97 98 template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up> 99 struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, true> 100 { 101 #ifndef _LIBCPP_CXX03_LANG 102 typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::template rebind<_Up> type; 103 #else 104 typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::template rebind<_Up>::other type; 105 #endif 106 }; 107 108 template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up> 109 struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false> 110 { 111 typedef _Sp<_Up, _Args...> type; 112 }; 113 114 template <class _Ptr, class = void> 115 struct __pointer_traits_impl {}; 116 117 template <class _Ptr> 118 struct __pointer_traits_impl<_Ptr, __void_t<typename __pointer_traits_element_type<_Ptr>::type> > { 119 typedef _Ptr pointer; 120 typedef typename __pointer_traits_element_type<pointer>::type element_type; 121 typedef typename __pointer_traits_difference_type<pointer>::type difference_type; 122 123 #ifndef _LIBCPP_CXX03_LANG 124 template <class _Up> using rebind = typename __pointer_traits_rebind<pointer, _Up>::type; 125 #else 126 template <class _Up> struct rebind 127 {typedef typename __pointer_traits_rebind<pointer, _Up>::type other;}; 128 #endif // _LIBCPP_CXX03_LANG 129 130 private: 131 struct __nat {}; 132 public: 133 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 134 static pointer pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) 135 {return pointer::pointer_to(__r);} 136 }; 137 138 template <class _Ptr> 139 struct _LIBCPP_TEMPLATE_VIS pointer_traits : __pointer_traits_impl<_Ptr> {}; 140 141 template <class _Tp> 142 struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*> 143 { 144 typedef _Tp* pointer; 145 typedef _Tp element_type; 146 typedef ptrdiff_t difference_type; 147 148 #ifndef _LIBCPP_CXX03_LANG 149 template <class _Up> using rebind = _Up*; 150 #else 151 template <class _Up> struct rebind {typedef _Up* other;}; 152 #endif 153 154 private: 155 struct __nat {}; 156 public: 157 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 158 static pointer pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) _NOEXCEPT 159 {return _VSTD::addressof(__r);} 160 }; 161 162 #ifndef _LIBCPP_CXX03_LANG 163 template <class _From, class _To> 164 using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>; 165 #else 166 template <class _From, class _To> 167 using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>::other; 168 #endif 169 170 // to_address 171 172 template <class _Pointer, class = void> 173 struct __to_address_helper; 174 175 template <class _Tp> 176 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 177 _Tp* __to_address(_Tp* __p) _NOEXCEPT { 178 static_assert(!is_function<_Tp>::value, "_Tp is a function type"); 179 return __p; 180 } 181 182 template <class _Pointer, class = void> 183 struct _HasToAddress : false_type {}; 184 185 template <class _Pointer> 186 struct _HasToAddress<_Pointer, 187 decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) 188 > : true_type {}; 189 190 template <class _Pointer, class = void> 191 struct _HasArrow : false_type {}; 192 193 template <class _Pointer> 194 struct _HasArrow<_Pointer, 195 decltype((void)std::declval<const _Pointer&>().operator->()) 196 > : true_type {}; 197 198 template <class _Pointer> 199 struct _IsFancyPointer { 200 static const bool value = _HasArrow<_Pointer>::value || _HasToAddress<_Pointer>::value; 201 }; 202 203 // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers 204 template <class _Pointer, class = __enable_if_t< 205 _And<is_class<_Pointer>, _IsFancyPointer<_Pointer> >::value 206 > > 207 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 208 __decay_t<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))> 209 __to_address(const _Pointer& __p) _NOEXCEPT { 210 return __to_address_helper<_Pointer>::__call(__p); 211 } 212 213 template <class _Pointer, class> 214 struct __to_address_helper { 215 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 216 static decltype(_VSTD::__to_address(std::declval<const _Pointer&>().operator->())) 217 __call(const _Pointer& __p) _NOEXCEPT { 218 return _VSTD::__to_address(__p.operator->()); 219 } 220 }; 221 222 template <class _Pointer> 223 struct __to_address_helper<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))> { 224 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 225 static decltype(pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) 226 __call(const _Pointer& __p) _NOEXCEPT { 227 return pointer_traits<_Pointer>::to_address(__p); 228 } 229 }; 230 231 #if _LIBCPP_STD_VER >= 20 232 template <class _Tp> 233 inline _LIBCPP_INLINE_VISIBILITY constexpr 234 auto to_address(_Tp *__p) noexcept { 235 return _VSTD::__to_address(__p); 236 } 237 238 template <class _Pointer> 239 inline _LIBCPP_INLINE_VISIBILITY constexpr 240 auto to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p)) { 241 return _VSTD::__to_address(__p); 242 } 243 #endif 244 245 _LIBCPP_END_NAMESPACE_STD 246 247 #endif // _LIBCPP___MEMORY_POINTER_TRAITS_H 248