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> 115 struct _LIBCPP_TEMPLATE_VIS pointer_traits 116 { 117 typedef _Ptr pointer; 118 typedef typename __pointer_traits_element_type<pointer>::type element_type; 119 typedef typename __pointer_traits_difference_type<pointer>::type difference_type; 120 121 #ifndef _LIBCPP_CXX03_LANG 122 template <class _Up> using rebind = typename __pointer_traits_rebind<pointer, _Up>::type; 123 #else 124 template <class _Up> struct rebind 125 {typedef typename __pointer_traits_rebind<pointer, _Up>::type other;}; 126 #endif // _LIBCPP_CXX03_LANG 127 128 private: 129 struct __nat {}; 130 public: 131 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 132 static pointer pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) 133 {return pointer::pointer_to(__r);} 134 }; 135 136 template <class _Tp> 137 struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*> 138 { 139 typedef _Tp* pointer; 140 typedef _Tp element_type; 141 typedef ptrdiff_t difference_type; 142 143 #ifndef _LIBCPP_CXX03_LANG 144 template <class _Up> using rebind = _Up*; 145 #else 146 template <class _Up> struct rebind {typedef _Up* other;}; 147 #endif 148 149 private: 150 struct __nat {}; 151 public: 152 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20 153 static pointer pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) _NOEXCEPT 154 {return _VSTD::addressof(__r);} 155 }; 156 157 #ifndef _LIBCPP_CXX03_LANG 158 template <class _From, class _To> 159 using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>; 160 #else 161 template <class _From, class _To> 162 using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>::other; 163 #endif 164 165 // to_address 166 167 template <class _Pointer, class = void> 168 struct __to_address_helper; 169 170 template <class _Tp> 171 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 172 _Tp* __to_address(_Tp* __p) _NOEXCEPT { 173 static_assert(!is_function<_Tp>::value, "_Tp is a function type"); 174 return __p; 175 } 176 177 template <class _Pointer, class = void> 178 struct _HasToAddress : false_type {}; 179 180 template <class _Pointer> 181 struct _HasToAddress<_Pointer, 182 decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) 183 > : true_type {}; 184 185 template <class _Pointer, class = void> 186 struct _HasArrow : false_type {}; 187 188 template <class _Pointer> 189 struct _HasArrow<_Pointer, 190 decltype((void)std::declval<const _Pointer&>().operator->()) 191 > : true_type {}; 192 193 template <class _Pointer> 194 struct _IsFancyPointer { 195 static const bool value = _HasArrow<_Pointer>::value || _HasToAddress<_Pointer>::value; 196 }; 197 198 // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers 199 template <class _Pointer, class = __enable_if_t< 200 _And<is_class<_Pointer>, _IsFancyPointer<_Pointer> >::value 201 > > 202 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 203 __decay_t<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))> 204 __to_address(const _Pointer& __p) _NOEXCEPT { 205 return __to_address_helper<_Pointer>::__call(__p); 206 } 207 208 template <class _Pointer, class> 209 struct __to_address_helper { 210 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 211 static decltype(_VSTD::__to_address(std::declval<const _Pointer&>().operator->())) 212 __call(const _Pointer& __p) _NOEXCEPT { 213 return _VSTD::__to_address(__p.operator->()); 214 } 215 }; 216 217 template <class _Pointer> 218 struct __to_address_helper<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))> { 219 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 220 static decltype(pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) 221 __call(const _Pointer& __p) _NOEXCEPT { 222 return pointer_traits<_Pointer>::to_address(__p); 223 } 224 }; 225 226 #if _LIBCPP_STD_VER >= 20 227 template <class _Tp> 228 inline _LIBCPP_INLINE_VISIBILITY constexpr 229 auto to_address(_Tp *__p) noexcept { 230 return _VSTD::__to_address(__p); 231 } 232 233 template <class _Pointer> 234 inline _LIBCPP_INLINE_VISIBILITY constexpr 235 auto to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p)) { 236 return _VSTD::__to_address(__p); 237 } 238 #endif 239 240 _LIBCPP_END_NAMESPACE_STD 241 242 #endif // _LIBCPP___MEMORY_POINTER_TRAITS_H 243