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{ 43 typedef _LIBCPP_NODEBUG typename _Ptr::element_type type; 44}; 45 46template <template <class, class...> class _Sp, class _Tp, class ..._Args> 47struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, true> 48{ 49 typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::element_type type; 50}; 51 52template <template <class, class...> class _Sp, class _Tp, class ..._Args> 53struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, false> 54{ 55 typedef _LIBCPP_NODEBUG _Tp type; 56}; 57 58template <class _Tp, class = void> 59struct __has_difference_type : false_type {}; 60 61template <class _Tp> 62struct __has_difference_type<_Tp, __void_t<typename _Tp::difference_type> > : true_type {}; 63 64template <class _Ptr, bool = __has_difference_type<_Ptr>::value> 65struct __pointer_traits_difference_type 66{ 67 typedef _LIBCPP_NODEBUG ptrdiff_t type; 68}; 69 70template <class _Ptr> 71struct __pointer_traits_difference_type<_Ptr, true> 72{ 73 typedef _LIBCPP_NODEBUG typename _Ptr::difference_type type; 74}; 75 76template <class _Tp, class _Up> 77struct __has_rebind 78{ 79private: 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 84public: 85 static const bool value = decltype(__test<_Tp>(0))::value; 86}; 87 88template <class _Tp, class _Up, bool = __has_rebind<_Tp, _Up>::value> 89struct __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 98template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up> 99struct __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 108template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up> 109struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false> 110{ 111 typedef _Sp<_Up, _Args...> type; 112}; 113 114template <class _Ptr> 115struct _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 128private: 129 struct __nat {}; 130public: 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 136template <class _Tp> 137struct _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 149private: 150 struct __nat {}; 151public: 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 158template <class _From, class _To> 159using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>; 160#else 161template <class _From, class _To> 162using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>::other; 163#endif 164 165// to_address 166 167template <class _Pointer, class = void> 168struct __to_address_helper; 169 170template <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 177template <class _Pointer, class = void> 178struct _HasToAddress : false_type {}; 179 180template <class _Pointer> 181struct _HasToAddress<_Pointer, 182 decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) 183> : true_type {}; 184 185template <class _Pointer, class = void> 186struct _HasArrow : false_type {}; 187 188template <class _Pointer> 189struct _HasArrow<_Pointer, 190 decltype((void)std::declval<const _Pointer&>().operator->()) 191> : true_type {}; 192 193template <class _Pointer> 194struct _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 199template <class _Pointer, class = __enable_if_t< 200 _And<is_class<_Pointer>, _IsFancyPointer<_Pointer> >::value 201> > 202_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR 203typename decay<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))>::type 204__to_address(const _Pointer& __p) _NOEXCEPT { 205 return __to_address_helper<_Pointer>::__call(__p); 206} 207 208template <class _Pointer, class> 209struct __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 217template <class _Pointer> 218struct __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 > 17 227template <class _Tp> 228inline _LIBCPP_INLINE_VISIBILITY constexpr 229auto to_address(_Tp *__p) noexcept { 230 return _VSTD::__to_address(__p); 231} 232 233template <class _Pointer> 234inline _LIBCPP_INLINE_VISIBILITY constexpr 235auto 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