Line data Source code
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 :
31 : template <class _Tp, class = void>
32 : struct __has_element_type : false_type {};
33 :
34 : template <class _Tp>
35 : struct __has_element_type<_Tp, __void_t<typename _Tp::element_type> > : true_type {};
36 :
37 : template <class _Ptr, bool = __has_element_type<_Ptr>::value>
38 : struct __pointer_traits_element_type;
39 :
40 : template <class _Ptr>
41 : struct __pointer_traits_element_type<_Ptr, true>
42 : {
43 : typedef _LIBCPP_NODEBUG typename _Ptr::element_type type;
44 : };
45 :
46 : template <template <class, class...> class _Sp, class _Tp, class ..._Args>
47 : struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, true>
48 : {
49 : typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::element_type type;
50 : };
51 :
52 : template <template <class, class...> class _Sp, class _Tp, class ..._Args>
53 : struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, false>
54 : {
55 : typedef _LIBCPP_NODEBUG _Tp type;
56 : };
57 :
58 : template <class _Tp, class = void>
59 : struct __has_difference_type : false_type {};
60 :
61 : template <class _Tp>
62 : struct __has_difference_type<_Tp, __void_t<typename _Tp::difference_type> > : true_type {};
63 :
64 : template <class _Ptr, bool = __has_difference_type<_Ptr>::value>
65 : struct __pointer_traits_difference_type
66 : {
67 : typedef _LIBCPP_NODEBUG ptrdiff_t type;
68 : };
69 :
70 : template <class _Ptr>
71 : struct __pointer_traits_difference_type<_Ptr, true>
72 : {
73 : typedef _LIBCPP_NODEBUG typename _Ptr::difference_type type;
74 : };
75 :
76 : template <class _Tp, class _Up>
77 : struct __has_rebind
78 : {
79 : private:
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
84 : public:
85 : static const bool value = decltype(__test<_Tp>(0))::value;
86 : };
87 :
88 : template <class _Tp, class _Up, bool = __has_rebind<_Tp, _Up>::value>
89 : struct __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 :
98 : template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up>
99 : struct __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 :
108 : template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up>
109 : struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false>
110 : {
111 : typedef _Sp<_Up, _Args...> type;
112 : };
113 :
114 : template <class _Ptr>
115 : struct _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 :
128 : private:
129 : struct __nat {};
130 : public:
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 :
136 : template <class _Tp>
137 : struct _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 :
149 : private:
150 : struct __nat {};
151 : public:
152 : _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
153 15798351 : static pointer pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) _NOEXCEPT
154 15798351 : {return _VSTD::addressof(__r);}
155 : };
156 :
157 : #ifndef _LIBCPP_CXX03_LANG
158 : template <class _From, class _To>
159 : using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>;
160 : #else
161 : template <class _From, class _To>
162 : using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>::other;
163 : #endif
164 :
165 : // to_address
166 :
167 : template <class _Pointer, class = void>
168 : struct __to_address_helper;
169 :
170 : template <class _Tp>
171 : _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
172 13951866 : _Tp* __to_address(_Tp* __p) _NOEXCEPT {
173 : static_assert(!is_function<_Tp>::value, "_Tp is a function type");
174 13951866 : return __p;
175 : }
176 :
177 : template <class _Pointer, class = void>
178 : struct _HasToAddress : false_type {};
179 :
180 : template <class _Pointer>
181 : struct _HasToAddress<_Pointer,
182 : decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))
183 : > : true_type {};
184 :
185 : template <class _Pointer, class = void>
186 : struct _HasArrow : false_type {};
187 :
188 : template <class _Pointer>
189 : struct _HasArrow<_Pointer,
190 : decltype((void)std::declval<const _Pointer&>().operator->())
191 : > : true_type {};
192 :
193 : template <class _Pointer>
194 : struct _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
199 : template <class _Pointer, class = __enable_if_t<
200 : _And<is_class<_Pointer>, _IsFancyPointer<_Pointer> >::value
201 : > >
202 : _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
203 : typename decay<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))>::type
204 3321 : __to_address(const _Pointer& __p) _NOEXCEPT {
205 3321 : return __to_address_helper<_Pointer>::__call(__p);
206 : }
207 :
208 : template <class _Pointer, class>
209 : struct __to_address_helper {
210 : _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
211 : static decltype(_VSTD::__to_address(std::declval<const _Pointer&>().operator->()))
212 3321 : __call(const _Pointer& __p) _NOEXCEPT {
213 3321 : return _VSTD::__to_address(__p.operator->());
214 0 : }
215 : };
216 :
217 : template <class _Pointer>
218 : struct __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
227 : template <class _Tp>
228 : inline _LIBCPP_INLINE_VISIBILITY constexpr
229 : auto to_address(_Tp *__p) noexcept {
230 : return _VSTD::__to_address(__p);
231 : }
232 :
233 : template <class _Pointer>
234 : inline _LIBCPP_INLINE_VISIBILITY constexpr
235 : auto 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
|