brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.9 KiB · 62fcd93 Raw
272 lines · c
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-exception7//8//===----------------------------------------------------------------------===//9 10#ifndef _LIBCPP___MEMORY_POINTER_TRAITS_H11#define _LIBCPP___MEMORY_POINTER_TRAITS_H12 13#include <__config>14#include <__cstddef/ptrdiff_t.h>15#include <__memory/addressof.h>16#include <__type_traits/conditional.h>17#include <__type_traits/conjunction.h>18#include <__type_traits/decay.h>19#include <__type_traits/detected_or.h>20#include <__type_traits/enable_if.h>21#include <__type_traits/integral_constant.h>22#include <__type_traits/is_class.h>23#include <__type_traits/is_function.h>24#include <__type_traits/is_void.h>25#include <__type_traits/nat.h>26#include <__type_traits/void_t.h>27#include <__utility/declval.h>28#include <__utility/forward.h>29 30#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)31#  pragma GCC system_header32#endif33 34_LIBCPP_PUSH_MACROS35#include <__undef_macros>36 37_LIBCPP_BEGIN_NAMESPACE_STD38 39template <class _Ptr>40struct __pointer_traits_element_type_impl {};41 42template <template <class, class...> class _Sp, class _Tp, class... _Args>43struct __pointer_traits_element_type_impl<_Sp<_Tp, _Args...> > {44  using type _LIBCPP_NODEBUG = _Tp;45};46 47template <class _Ptr, class = void>48struct __pointer_traits_element_type : __pointer_traits_element_type_impl<_Ptr> {};49 50template <class _Ptr>51struct __pointer_traits_element_type<_Ptr, __void_t<typename _Ptr::element_type> > {52  using type _LIBCPP_NODEBUG = typename _Ptr::element_type;53};54 55template <class _Tp, class _Up>56struct __pointer_traits_rebind_impl {57  static_assert(false, "Cannot rebind pointer; did you forget to add a rebind member to your pointer?");58};59 60template <template <class, class...> class _Sp, class _Tp, class... _Args, class _Up>61struct __pointer_traits_rebind_impl<_Sp<_Tp, _Args...>, _Up> {62  using type _LIBCPP_NODEBUG = _Sp<_Up, _Args...>;63};64 65template <class _Tp, class _Up, class = void>66struct __pointer_traits_rebind : __pointer_traits_rebind_impl<_Tp, _Up> {};67 68template <class _Tp, class _Up>69struct __pointer_traits_rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up> > > {70#ifndef _LIBCPP_CXX03_LANG71  using type _LIBCPP_NODEBUG = typename _Tp::template rebind<_Up>;72#else73  using type _LIBCPP_NODEBUG = typename _Tp::template rebind<_Up>::other;74#endif75};76 77template <class _Tp>78using __difference_type_member _LIBCPP_NODEBUG = typename _Tp::difference_type;79 80template <class _Ptr, class = void>81struct __pointer_traits_impl {};82 83template <class _Ptr>84struct __pointer_traits_impl<_Ptr, __void_t<typename __pointer_traits_element_type<_Ptr>::type> > {85  typedef _Ptr pointer;86  typedef typename __pointer_traits_element_type<pointer>::type element_type;87  using difference_type = __detected_or_t<ptrdiff_t, __difference_type_member, pointer>;88 89#ifndef _LIBCPP_CXX03_LANG90  template <class _Up>91  using rebind = typename __pointer_traits_rebind<pointer, _Up>::type;92#else93  template <class _Up>94  struct rebind {95    typedef typename __pointer_traits_rebind<pointer, _Up>::type other;96  };97#endif // _LIBCPP_CXX03_LANG98 99public:100  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer101  pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) {102    return pointer::pointer_to(__r);103  }104};105 106template <class _Ptr>107struct pointer_traits : __pointer_traits_impl<_Ptr> {};108 109template <class _Tp>110struct pointer_traits<_Tp*> {111  typedef _Tp* pointer;112  typedef _Tp element_type;113  typedef ptrdiff_t difference_type;114 115#ifndef _LIBCPP_CXX03_LANG116  template <class _Up>117  using rebind = _Up*;118#else119  template <class _Up>120  struct rebind {121    typedef _Up* other;122  };123#endif124 125public:126  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer127  pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) _NOEXCEPT {128    return std::addressof(__r);129  }130};131 132#ifndef _LIBCPP_CXX03_LANG133template <class _From, class _To>134using __rebind_pointer_t _LIBCPP_NODEBUG = typename pointer_traits<_From>::template rebind<_To>;135#else136template <class _From, class _To>137using __rebind_pointer_t _LIBCPP_NODEBUG = typename pointer_traits<_From>::template rebind<_To>::other;138#endif139 140// to_address141 142template <class _Pointer, class = void>143struct __to_address_helper;144 145template <class _Tp>146_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __to_address(_Tp* __p) _NOEXCEPT {147  static_assert(!is_function<_Tp>::value, "_Tp is a function type");148  return __p;149}150 151template <class _Pointer, class = void>152struct _HasToAddress : false_type {};153 154template <class _Pointer>155struct _HasToAddress<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) >156    : true_type {};157 158template <class _Pointer, class = void>159struct _HasArrow : false_type {};160 161template <class _Pointer>162struct _HasArrow<_Pointer, decltype((void)std::declval<const _Pointer&>().operator->()) > : true_type {};163 164template <class _Pointer>165struct _IsFancyPointer {166  static const bool value = _HasArrow<_Pointer>::value || _HasToAddress<_Pointer>::value;167};168 169// enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers170template <class _Pointer, __enable_if_t< _And<is_class<_Pointer>, _IsFancyPointer<_Pointer> >::value, int> = 0>171_LIBCPP_HIDE_FROM_ABI172_LIBCPP_CONSTEXPR __decay_t<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))>173__to_address(const _Pointer& __p) _NOEXCEPT {174  return __to_address_helper<_Pointer>::__call(__p);175}176 177template <class _Pointer, class>178struct __to_address_helper {179  _LIBCPP_HIDE_FROM_ABI180  _LIBCPP_CONSTEXPR static decltype(std::__to_address(std::declval<const _Pointer&>().operator->()))181  __call(const _Pointer& __p) _NOEXCEPT {182    return std::__to_address(__p.operator->());183  }184};185 186template <class _Pointer>187struct __to_address_helper<_Pointer,188                           decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))> {189  _LIBCPP_HIDE_FROM_ABI190  _LIBCPP_CONSTEXPR static decltype(pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))191  __call(const _Pointer& __p) _NOEXCEPT {192    return pointer_traits<_Pointer>::to_address(__p);193  }194};195 196#if _LIBCPP_STD_VER >= 20197template <class _Tp>198inline _LIBCPP_HIDE_FROM_ABI constexpr auto to_address(_Tp* __p) noexcept {199  return std::__to_address(__p);200}201 202template <class _Pointer>203inline _LIBCPP_HIDE_FROM_ABI constexpr auto to_address(const _Pointer& __p) noexcept204    -> decltype(std::__to_address(__p)) {205  return std::__to_address(__p);206}207#endif208 209#if _LIBCPP_STD_VER >= 23210 211template <class _Tp>212struct __pointer_of {};213 214template <class _Tp>215concept __has_pointer_member = requires { typename _Tp::pointer; };216 217template <class _Tp>218concept __has_element_type_member = requires { typename _Tp::element_type; };219 220template <class _Tp>221  requires __has_pointer_member<_Tp>222struct __pointer_of<_Tp> {223  using type _LIBCPP_NODEBUG = typename _Tp::pointer;224};225 226template <class _Tp>227  requires(!__has_pointer_member<_Tp> && __has_element_type_member<_Tp>)228struct __pointer_of<_Tp> {229  using type _LIBCPP_NODEBUG = typename _Tp::element_type*;230};231 232template <class _Tp>233  requires(!__has_pointer_member<_Tp> && !__has_element_type_member<_Tp> &&234           __has_element_type_member<pointer_traits<_Tp>>)235struct __pointer_of<_Tp> {236  using type _LIBCPP_NODEBUG = typename pointer_traits<_Tp>::element_type*;237};238 239template <typename _Tp>240using __pointer_of_t _LIBCPP_NODEBUG = typename __pointer_of<_Tp>::type;241 242template <typename _Tp, typename _Up>243using __pointer_of_or_t _LIBCPP_NODEBUG = __detected_or_t<_Up, __pointer_of_t, _Tp>;244 245template <class _Smart>246concept __resettable_smart_pointer = requires(_Smart __s) { __s.reset(); };247 248template <class _Smart, class _Pointer, class... _Args>249concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p, _Args... __args) {250  __s.reset(static_cast<__pointer_of_or_t<_Smart, _Pointer>>(__p), std::forward<_Args>(__args)...);251};252 253#endif254 255// This function ensures safe conversions between fancy pointers at compile-time, where we avoid casts from/to256// `__void_pointer` by obtaining the underlying raw pointer from the fancy pointer using `std::to_address`,257// then dereferencing it to retrieve the pointed-to object, and finally constructing the target fancy pointer258// to that object using the `std::pointer_traits<>::pointer_to` function.259template <class _PtrTo, class _PtrFrom>260_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _PtrTo __static_fancy_pointer_cast(const _PtrFrom& __p) {261  using __ptr_traits   = pointer_traits<_PtrTo>;262  using __element_type = typename __ptr_traits::element_type;263  return __p ? __ptr_traits::pointer_to(*static_cast<__element_type*>(std::addressof(*__p)))264             : static_cast<_PtrTo>(nullptr);265}266 267_LIBCPP_END_NAMESPACE_STD268 269_LIBCPP_POP_MACROS270 271#endif // _LIBCPP___MEMORY_POINTER_TRAITS_H272