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