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