Warning: This file is not a C or C++ file. It does not have highlighting.

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 <__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/enable_if.h>
20#include <__type_traits/integral_constant.h>
21#include <__type_traits/is_class.h>
22#include <__type_traits/is_function.h>
23#include <__type_traits/is_void.h>
24#include <__type_traits/void_t.h>
25#include <__utility/declval.h>
26#include <__utility/forward.h>
27
28#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
29# pragma GCC system_header
30#endif
31
32_LIBCPP_PUSH_MACROS
33#include <__undef_macros>
34
35_LIBCPP_BEGIN_NAMESPACE_STD
36
37// clang-format off
38#define _LIBCPP_CLASS_TRAITS_HAS_XXX(NAME, PROPERTY) \
39 template <class _Tp, class = void> \
40 struct NAME : false_type {}; \
41 template <class _Tp> \
42 struct NAME<_Tp, __void_t<typename _Tp::PROPERTY> > : true_type {}
43// clang-format on
44
45_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_pointer, pointer);
46_LIBCPP_CLASS_TRAITS_HAS_XXX(__has_element_type, element_type);
47
48template <class _Ptr, bool = __has_element_type<_Ptr>::value>
49struct __pointer_traits_element_type {};
50
51template <class _Ptr>
52struct __pointer_traits_element_type<_Ptr, true> {
53 using type _LIBCPP_NODEBUG = typename _Ptr::element_type;
54};
55
56template <template <class, class...> class _Sp, class _Tp, class... _Args>
57struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, true> {
58 using type _LIBCPP_NODEBUG = typename _Sp<_Tp, _Args...>::element_type;
59};
60
61template <template <class, class...> class _Sp, class _Tp, class... _Args>
62struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, false> {
63 using type _LIBCPP_NODEBUG = _Tp;
64};
65
66template <class _Tp, class = void>
67struct __has_difference_type : false_type {};
68
69template <class _Tp>
70struct __has_difference_type<_Tp, __void_t<typename _Tp::difference_type> > : true_type {};
71
72template <class _Ptr, bool = __has_difference_type<_Ptr>::value>
73struct __pointer_traits_difference_type {
74 using type _LIBCPP_NODEBUG = ptrdiff_t;
75};
76
77template <class _Ptr>
78struct __pointer_traits_difference_type<_Ptr, true> {
79 using type _LIBCPP_NODEBUG = typename _Ptr::difference_type;
80};
81
82template <class _Tp, class _Up>
83struct __has_rebind {
84private:
85 template <class _Xp>
86 static false_type __test(...);
87 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
88 template <class _Xp>
89 static true_type __test(typename _Xp::template rebind<_Up>* = 0);
90 _LIBCPP_SUPPRESS_DEPRECATED_POP
91
92public:
93 static const bool value = decltype(__test<_Tp>(0))::value;
94};
95
96template <class _Tp, class _Up, bool = __has_rebind<_Tp, _Up>::value>
97struct __pointer_traits_rebind {
98#ifndef _LIBCPP_CXX03_LANG
99 using type _LIBCPP_NODEBUG = typename _Tp::template rebind<_Up>;
100#else
101 using type _LIBCPP_NODEBUG = typename _Tp::template rebind<_Up>::other;
102#endif
103};
104
105template <template <class, class...> class _Sp, class _Tp, class... _Args, class _Up>
106struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, true> {
107#ifndef _LIBCPP_CXX03_LANG
108 using type _LIBCPP_NODEBUG = typename _Sp<_Tp, _Args...>::template rebind<_Up>;
109#else
110 using type _LIBCPP_NODEBUG = typename _Sp<_Tp, _Args...>::template rebind<_Up>::other;
111#endif
112};
113
114template <template <class, class...> class _Sp, class _Tp, class... _Args, class _Up>
115struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false> {
116 typedef _Sp<_Up, _Args...> type;
117};
118
119template <class _Ptr, class = void>
120struct __pointer_traits_impl {};
121
122template <class _Ptr>
123struct __pointer_traits_impl<_Ptr, __void_t<typename __pointer_traits_element_type<_Ptr>::type> > {
124 typedef _Ptr pointer;
125 typedef typename __pointer_traits_element_type<pointer>::type element_type;
126 typedef typename __pointer_traits_difference_type<pointer>::type difference_type;
127
128#ifndef _LIBCPP_CXX03_LANG
129 template <class _Up>
130 using rebind = typename __pointer_traits_rebind<pointer, _Up>::type;
131#else
132 template <class _Up>
133 struct rebind {
134 typedef typename __pointer_traits_rebind<pointer, _Up>::type other;
135 };
136#endif // _LIBCPP_CXX03_LANG
137
138private:
139 struct __nat {};
140
141public:
142 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer
143 pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) {
144 return pointer::pointer_to(__r);
145 }
146};
147
148template <class _Ptr>
149struct pointer_traits : __pointer_traits_impl<_Ptr> {};
150
151template <class _Tp>
152struct pointer_traits<_Tp*> {
153 typedef _Tp* pointer;
154 typedef _Tp element_type;
155 typedef ptrdiff_t difference_type;
156
157#ifndef _LIBCPP_CXX03_LANG
158 template <class _Up>
159 using rebind = _Up*;
160#else
161 template <class _Up>
162 struct rebind {
163 typedef _Up* other;
164 };
165#endif
166
167private:
168 struct __nat {};
169
170public:
171 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer
172 pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) _NOEXCEPT {
173 return std::addressof(__r);
174 }
175};
176
177#ifndef _LIBCPP_CXX03_LANG
178template <class _From, class _To>
179using __rebind_pointer_t _LIBCPP_NODEBUG = typename pointer_traits<_From>::template rebind<_To>;
180#else
181template <class _From, class _To>
182using __rebind_pointer_t _LIBCPP_NODEBUG = typename pointer_traits<_From>::template rebind<_To>::other;
183#endif
184
185// to_address
186
187template <class _Pointer, class = void>
188struct __to_address_helper;
189
190template <class _Tp>
191_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __to_address(_Tp* __p) _NOEXCEPT {
192 static_assert(!is_function<_Tp>::value, "_Tp is a function type");
193 return __p;
194}
195
196template <class _Pointer, class = void>
197struct _HasToAddress : false_type {};
198
199template <class _Pointer>
200struct _HasToAddress<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) >
201 : true_type {};
202
203template <class _Pointer, class = void>
204struct _HasArrow : false_type {};
205
206template <class _Pointer>
207struct _HasArrow<_Pointer, decltype((void)std::declval<const _Pointer&>().operator->()) > : true_type {};
208
209template <class _Pointer>
210struct _IsFancyPointer {
211 static const bool value = _HasArrow<_Pointer>::value || _HasToAddress<_Pointer>::value;
212};
213
214// enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers
215template <class _Pointer, __enable_if_t< _And<is_class<_Pointer>, _IsFancyPointer<_Pointer> >::value, int> = 0>
216_LIBCPP_HIDE_FROM_ABI
217_LIBCPP_CONSTEXPR __decay_t<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))>
218__to_address(const _Pointer& __p) _NOEXCEPT {
219 return __to_address_helper<_Pointer>::__call(__p);
220}
221
222template <class _Pointer, class>
223struct __to_address_helper {
224 _LIBCPP_HIDE_FROM_ABI
225 _LIBCPP_CONSTEXPR static decltype(std::__to_address(std::declval<const _Pointer&>().operator->()))
226 __call(const _Pointer& __p) _NOEXCEPT {
227 return std::__to_address(__p.operator->());
228 }
229};
230
231template <class _Pointer>
232struct __to_address_helper<_Pointer,
233 decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))> {
234 _LIBCPP_HIDE_FROM_ABI
235 _LIBCPP_CONSTEXPR static decltype(pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))
236 __call(const _Pointer& __p) _NOEXCEPT {
237 return pointer_traits<_Pointer>::to_address(__p);
238 }
239};
240
241#if _LIBCPP_STD_VER >= 20
242template <class _Tp>
243inline _LIBCPP_HIDE_FROM_ABI constexpr auto to_address(_Tp* __p) noexcept {
244 return std::__to_address(__p);
245}
246
247template <class _Pointer>
248inline _LIBCPP_HIDE_FROM_ABI constexpr auto to_address(const _Pointer& __p) noexcept
249 -> decltype(std::__to_address(__p)) {
250 return std::__to_address(__p);
251}
252#endif
253
254#if _LIBCPP_STD_VER >= 23
255
256template <class _Tp>
257struct __pointer_of {};
258
259template <class _Tp>
260 requires(__has_pointer<_Tp>::value)
261struct __pointer_of<_Tp> {
262 using type _LIBCPP_NODEBUG = typename _Tp::pointer;
263};
264
265template <class _Tp>
266 requires(!__has_pointer<_Tp>::value && __has_element_type<_Tp>::value)
267struct __pointer_of<_Tp> {
268 using type _LIBCPP_NODEBUG = typename _Tp::element_type*;
269};
270
271template <class _Tp>
272 requires(!__has_pointer<_Tp>::value && !__has_element_type<_Tp>::value &&
273 __has_element_type<pointer_traits<_Tp>>::value)
274struct __pointer_of<_Tp> {
275 using type _LIBCPP_NODEBUG = typename pointer_traits<_Tp>::element_type*;
276};
277
278template <typename _Tp>
279using __pointer_of_t _LIBCPP_NODEBUG = typename __pointer_of<_Tp>::type;
280
281template <class _Tp, class _Up>
282struct __pointer_of_or {
283 using type _LIBCPP_NODEBUG = _Up;
284};
285
286template <class _Tp, class _Up>
287 requires requires { typename __pointer_of_t<_Tp>; }
288struct __pointer_of_or<_Tp, _Up> {
289 using type _LIBCPP_NODEBUG = __pointer_of_t<_Tp>;
290};
291
292template <typename _Tp, typename _Up>
293using __pointer_of_or_t _LIBCPP_NODEBUG = typename __pointer_of_or<_Tp, _Up>::type;
294
295template <class _Smart>
296concept __resettable_smart_pointer = requires(_Smart __s) { __s.reset(); };
297
298template <class _Smart, class _Pointer, class... _Args>
299concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p, _Args... __args) {
300 __s.reset(static_cast<__pointer_of_or_t<_Smart, _Pointer>>(__p), std::forward<_Args>(__args)...);
301};
302
303#endif
304
305// This function ensures safe conversions between fancy pointers at compile-time, where we avoid casts from/to
306// `__void_pointer` by obtaining the underlying raw pointer from the fancy pointer using `std::to_address`,
307// then dereferencing it to retrieve the pointed-to object, and finally constructing the target fancy pointer
308// to that object using the `std::pointer_traits<>::pinter_to` function.
309template <class _PtrTo, class _PtrFrom>
310_LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI _PtrTo __static_fancy_pointer_cast(const _PtrFrom& __p) {
311 using __ptr_traits = pointer_traits<_PtrTo>;
312 using __element_type = typename __ptr_traits::element_type;
313 return __p ? __ptr_traits::pointer_to(*static_cast<__element_type*>(std::addressof(*__p)))
314 : static_cast<_PtrTo>(nullptr);
315}
316
317_LIBCPP_END_NAMESPACE_STD
318
319_LIBCPP_POP_MACROS
320
321#endif // _LIBCPP___MEMORY_POINTER_TRAITS_H
322

Warning: This file is not a C or C++ file. It does not have highlighting.

source code of libcxx/include/__memory/pointer_traits.h