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 <type_traits>
15 
16 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
17 #pragma GCC system_header
18 #endif
19 
20 _LIBCPP_PUSH_MACROS
21 #include <__undef_macros>
22 
23 _LIBCPP_BEGIN_NAMESPACE_STD
24 
25 template <class _Tp, class = void>
26 struct __has_element_type : false_type {};
27 
28 template <class _Tp>
29 struct __has_element_type<_Tp,
30               typename __void_t<typename _Tp::element_type>::type> : true_type {};
31 
32 template <class _Ptr, bool = __has_element_type<_Ptr>::value>
33 struct __pointer_traits_element_type;
34 
35 template <class _Ptr>
36 struct __pointer_traits_element_type<_Ptr, true>
37 {
38     typedef _LIBCPP_NODEBUG_TYPE typename _Ptr::element_type type;
39 };
40 
41 template <template <class, class...> class _Sp, class _Tp, class ..._Args>
42 struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, true>
43 {
44     typedef _LIBCPP_NODEBUG_TYPE typename _Sp<_Tp, _Args...>::element_type type;
45 };
46 
47 template <template <class, class...> class _Sp, class _Tp, class ..._Args>
48 struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, false>
49 {
50     typedef _LIBCPP_NODEBUG_TYPE _Tp type;
51 };
52 
53 template <class _Tp, class = void>
54 struct __has_difference_type : false_type {};
55 
56 template <class _Tp>
57 struct __has_difference_type<_Tp,
58             typename __void_t<typename _Tp::difference_type>::type> : true_type {};
59 
60 template <class _Ptr, bool = __has_difference_type<_Ptr>::value>
61 struct __pointer_traits_difference_type
62 {
63     typedef _LIBCPP_NODEBUG_TYPE ptrdiff_t type;
64 };
65 
66 template <class _Ptr>
67 struct __pointer_traits_difference_type<_Ptr, true>
68 {
69     typedef _LIBCPP_NODEBUG_TYPE typename _Ptr::difference_type type;
70 };
71 
72 template <class _Tp, class _Up>
73 struct __has_rebind
74 {
75 private:
76     struct __two {char __lx; char __lxx;};
77     template <class _Xp> static __two __test(...);
78     _LIBCPP_SUPPRESS_DEPRECATED_PUSH
79     template <class _Xp> static char __test(typename _Xp::template rebind<_Up>* = 0);
80     _LIBCPP_SUPPRESS_DEPRECATED_POP
81 public:
82     static const bool value = sizeof(__test<_Tp>(0)) == 1;
83 };
84 
85 template <class _Tp, class _Up, bool = __has_rebind<_Tp, _Up>::value>
86 struct __pointer_traits_rebind
87 {
88 #ifndef _LIBCPP_CXX03_LANG
89     typedef _LIBCPP_NODEBUG_TYPE typename _Tp::template rebind<_Up> type;
90 #else
91     typedef _LIBCPP_NODEBUG_TYPE typename _Tp::template rebind<_Up>::other type;
92 #endif
93 };
94 
95 template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up>
96 struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, true>
97 {
98 #ifndef _LIBCPP_CXX03_LANG
99     typedef _LIBCPP_NODEBUG_TYPE typename _Sp<_Tp, _Args...>::template rebind<_Up> type;
100 #else
101     typedef _LIBCPP_NODEBUG_TYPE typename _Sp<_Tp, _Args...>::template rebind<_Up>::other type;
102 #endif
103 };
104 
105 template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up>
106 struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false>
107 {
108     typedef _Sp<_Up, _Args...> type;
109 };
110 
111 template <class _Ptr>
112 struct _LIBCPP_TEMPLATE_VIS pointer_traits
113 {
114     typedef _Ptr                                                     pointer;
115     typedef typename __pointer_traits_element_type<pointer>::type    element_type;
116     typedef typename __pointer_traits_difference_type<pointer>::type difference_type;
117 
118 #ifndef _LIBCPP_CXX03_LANG
119     template <class _Up> using rebind = typename __pointer_traits_rebind<pointer, _Up>::type;
120 #else
121     template <class _Up> struct rebind
122         {typedef typename __pointer_traits_rebind<pointer, _Up>::type other;};
123 #endif  // _LIBCPP_CXX03_LANG
124 
125 private:
126     struct __nat {};
127 public:
128     _LIBCPP_INLINE_VISIBILITY
129     static pointer pointer_to(typename conditional<is_void<element_type>::value,
130                                            __nat, element_type>::type& __r)
131         {return pointer::pointer_to(__r);}
132 };
133 
134 template <class _Tp>
135 struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*>
136 {
137     typedef _Tp*      pointer;
138     typedef _Tp       element_type;
139     typedef ptrdiff_t difference_type;
140 
141 #ifndef _LIBCPP_CXX03_LANG
142     template <class _Up> using rebind = _Up*;
143 #else
144     template <class _Up> struct rebind {typedef _Up* other;};
145 #endif
146 
147 private:
148     struct __nat {};
149 public:
150     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
151     static pointer pointer_to(typename conditional<is_void<element_type>::value,
152                                       __nat, element_type>::type& __r) _NOEXCEPT
153         {return _VSTD::addressof(__r);}
154 };
155 
156 template <class _From, class _To>
157 struct __rebind_pointer {
158 #ifndef _LIBCPP_CXX03_LANG
159     typedef typename pointer_traits<_From>::template rebind<_To>        type;
160 #else
161     typedef typename pointer_traits<_From>::template rebind<_To>::other type;
162 #endif
163 };
164 
165 // to_address
166 
167 template <bool _UsePointerTraits> struct __to_address_helper;
168 
169 template <> struct __to_address_helper<true> {
170     template <class _Pointer>
171     using __return_type = decltype(pointer_traits<_Pointer>::to_address(_VSTD::declval<const _Pointer&>()));
172 
173     template <class _Pointer>
174     _LIBCPP_CONSTEXPR
175     static __return_type<_Pointer>
176     __do_it(const _Pointer &__p) _NOEXCEPT { return pointer_traits<_Pointer>::to_address(__p); }
177 };
178 
179 template <class _Pointer, bool _Dummy = true>
180 using __choose_to_address = __to_address_helper<_IsValidExpansion<__to_address_helper<_Dummy>::template __return_type, _Pointer>::value>;
181 
182 template <class _Tp>
183 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
184 _Tp*
185 __to_address(_Tp* __p) _NOEXCEPT
186 {
187     static_assert(!is_function<_Tp>::value, "_Tp is a function type");
188     return __p;
189 }
190 
191 template <class _Pointer>
192 inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
193 typename __choose_to_address<_Pointer>::template __return_type<_Pointer>
194 __to_address(const _Pointer& __p) _NOEXCEPT
195 {
196     return __choose_to_address<_Pointer>::__do_it(__p);
197 }
198 
199 template <> struct __to_address_helper<false> {
200     template <class _Pointer>
201     using __return_type = typename pointer_traits<_Pointer>::element_type*;
202 
203     template <class _Pointer>
204     _LIBCPP_CONSTEXPR
205     static __return_type<_Pointer>
206     __do_it(const _Pointer &__p) _NOEXCEPT { return _VSTD::__to_address(__p.operator->()); }
207 };
208 
209 
210 #if _LIBCPP_STD_VER > 17
211 template <class _Tp>
212 inline _LIBCPP_INLINE_VISIBILITY constexpr
213 _Tp*
214 to_address(_Tp* __p) _NOEXCEPT
215 {
216     static_assert(!is_function_v<_Tp>, "_Tp is a function type");
217     return __p;
218 }
219 
220 template <class _Pointer>
221 inline _LIBCPP_INLINE_VISIBILITY constexpr
222 auto
223 to_address(const _Pointer& __p) _NOEXCEPT
224 {
225     return _VSTD::__to_address(__p);
226 }
227 #endif
228 
229 _LIBCPP_END_NAMESPACE_STD
230 
231 _LIBCPP_POP_MACROS
232 
233 #endif  // _LIBCPP___MEMORY_POINTER_TRAITS_H
234