]>
Commit | Line | Data |
---|---|---|
45ba8f9f JW |
1 | // Pointer Traits -*- C++ -*- |
2 | ||
a945c346 | 3 | // Copyright (C) 2011-2024 Free Software Foundation, Inc. |
45ba8f9f JW |
4 | // |
5 | // This file is part of the GNU ISO C++ Library. This library is free | |
6 | // software; you can redistribute it and/or modify it under the | |
7 | // terms of the GNU General Public License as published by the | |
8 | // Free Software Foundation; either version 3, or (at your option) | |
9 | // any later version. | |
10 | ||
11 | // This library is distributed in the hope that it will be useful, | |
12 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | // GNU General Public License for more details. | |
15 | ||
16 | // Under Section 7 of GPL version 3, you are granted additional | |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
24 | ||
25 | /** @file bits/ptr_traits.h | |
26 | * This is an internal header file, included by other library headers. | |
27 | * Do not attempt to use it directly. @headername{memory} | |
28 | */ | |
29 | ||
30 | #ifndef _PTR_TRAITS_H | |
31 | #define _PTR_TRAITS_H 1 | |
32 | ||
734f5023 | 33 | #if __cplusplus >= 201103L |
45ba8f9f | 34 | |
e92e7c15 | 35 | #include <bits/move.h> |
45ba8f9f | 36 | |
24fe8c8e | 37 | #if __cplusplus > 201703L |
b8018e5c | 38 | #include <concepts> |
24fe8c8e JW |
39 | namespace __gnu_debug { struct _Safe_iterator_base; } |
40 | #endif | |
41 | ||
45ba8f9f JW |
42 | namespace std _GLIBCXX_VISIBILITY(default) |
43 | { | |
44 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
45 | ||
757146fb JW |
46 | /// @cond undocumented |
47 | ||
4f44c555 | 48 | class __undefined; |
45ba8f9f | 49 | |
b8018e5c JW |
50 | // For a specialization `SomeTemplate<T, Types...>` the member `type` is T, |
51 | // otherwise `type` is `__undefined`. | |
45ba8f9f | 52 | template<typename _Tp> |
4f44c555 JW |
53 | struct __get_first_arg |
54 | { using type = __undefined; }; | |
45ba8f9f | 55 | |
b8018e5c | 56 | template<template<typename, typename...> class _SomeTemplate, typename _Tp, |
4f44c555 | 57 | typename... _Types> |
b8018e5c | 58 | struct __get_first_arg<_SomeTemplate<_Tp, _Types...>> |
4f44c555 | 59 | { using type = _Tp; }; |
45ba8f9f | 60 | |
b8018e5c JW |
61 | // For a specialization `SomeTemplate<T, Args...>` and a type `U` the member |
62 | // `type` is `SomeTemplate<U, Args...>`, otherwise there is no member `type`. | |
45ba8f9f | 63 | template<typename _Tp, typename _Up> |
4f44c555 | 64 | struct __replace_first_arg |
a3a1620b | 65 | { }; |
45ba8f9f | 66 | |
b8018e5c | 67 | template<template<typename, typename...> class _SomeTemplate, typename _Up, |
4f44c555 | 68 | typename _Tp, typename... _Types> |
b8018e5c JW |
69 | struct __replace_first_arg<_SomeTemplate<_Tp, _Types...>, _Up> |
70 | { using type = _SomeTemplate<_Up, _Types...>; }; | |
45ba8f9f | 71 | |
b8018e5c JW |
72 | // Detect the element type of a pointer-like type. |
73 | template<typename _Ptr, typename = void> | |
74 | struct __ptr_traits_elem : __get_first_arg<_Ptr> | |
75 | { }; | |
45ba8f9f | 76 | |
b8018e5c | 77 | // Use _Ptr::element_type if is a valid type. |
03cb9ed8 JW |
78 | #if __cpp_concepts |
79 | template<typename _Ptr> requires requires { typename _Ptr::element_type; } | |
80 | struct __ptr_traits_elem<_Ptr, void> | |
81 | { using type = typename _Ptr::element_type; }; | |
82 | #else | |
b8018e5c JW |
83 | template<typename _Ptr> |
84 | struct __ptr_traits_elem<_Ptr, __void_t<typename _Ptr::element_type>> | |
85 | { using type = typename _Ptr::element_type; }; | |
03cb9ed8 | 86 | #endif |
45ba8f9f | 87 | |
45ba8f9f | 88 | template<typename _Ptr> |
b8018e5c | 89 | using __ptr_traits_elem_t = typename __ptr_traits_elem<_Ptr>::type; |
b8018e5c | 90 | |
757146fb JW |
91 | /// @endcond |
92 | ||
b8018e5c JW |
93 | // Define pointer_traits<P>::pointer_to. |
94 | template<typename _Ptr, typename _Elt, bool = is_void<_Elt>::value> | |
95 | struct __ptr_traits_ptr_to | |
96 | { | |
97 | using pointer = _Ptr; | |
98 | using element_type = _Elt; | |
99 | ||
100 | /** | |
101 | * @brief Obtain a pointer to an object | |
102 | * @param __r A reference to an object of type `element_type` | |
fca0f50b JW |
103 | * @return `pointer::pointer_to(__r)` |
104 | * @pre `pointer::pointer_to(__r)` is a valid expression. | |
b8018e5c JW |
105 | */ |
106 | static pointer | |
fca0f50b | 107 | pointer_to(element_type& __r) |
b8018e5c JW |
108 | #if __cpp_lib_concepts |
109 | requires requires { | |
fca0f50b | 110 | { pointer::pointer_to(__r) } -> convertible_to<pointer>; |
b8018e5c JW |
111 | } |
112 | #endif | |
fca0f50b | 113 | { return pointer::pointer_to(__r); } |
b8018e5c JW |
114 | }; |
115 | ||
116 | // Do not define pointer_traits<P>::pointer_to if element type is void. | |
117 | template<typename _Ptr, typename _Elt> | |
118 | struct __ptr_traits_ptr_to<_Ptr, _Elt, true> | |
119 | { }; | |
120 | ||
121 | // Partial specialization defining pointer_traits<T*>::pointer_to(T&). | |
122 | template<typename _Tp> | |
123 | struct __ptr_traits_ptr_to<_Tp*, _Tp, false> | |
124 | { | |
125 | using pointer = _Tp*; | |
126 | using element_type = _Tp; | |
127 | ||
128 | /** | |
129 | * @brief Obtain a pointer to an object | |
130 | * @param __r A reference to an object of type `element_type` | |
131 | * @return `addressof(__r)` | |
132 | */ | |
133 | static _GLIBCXX20_CONSTEXPR pointer | |
134 | pointer_to(element_type& __r) noexcept | |
135 | { return std::addressof(__r); } | |
136 | }; | |
137 | ||
138 | template<typename _Ptr, typename _Elt> | |
139 | struct __ptr_traits_impl : __ptr_traits_ptr_to<_Ptr, _Elt> | |
45ba8f9f | 140 | { |
4f44c555 | 141 | private: |
4f44c555 | 142 | template<typename _Tp> |
2b667beb | 143 | using __diff_t = typename _Tp::difference_type; |
a3a1620b | 144 | |
4f44c555 | 145 | template<typename _Tp, typename _Up> |
2b667beb | 146 | using __rebind = __type_identity<typename _Tp::template rebind<_Up>>; |
4f44c555 JW |
147 | |
148 | public: | |
149 | /// The pointer type. | |
150 | using pointer = _Ptr; | |
151 | ||
152 | /// The type pointed to. | |
b8018e5c | 153 | using element_type = _Elt; |
45ba8f9f | 154 | |
4f44c555 | 155 | /// The type used to represent the difference between two pointers. |
2b667beb | 156 | using difference_type = __detected_or_t<ptrdiff_t, __diff_t, _Ptr>; |
4f44c555 JW |
157 | |
158 | /// A pointer to a different type. | |
45ba8f9f | 159 | template<typename _Up> |
2b667beb JW |
160 | using rebind = typename __detected_or_t<__replace_first_arg<_Ptr, _Up>, |
161 | __rebind, _Ptr, _Up>::type; | |
b8018e5c | 162 | }; |
4f44c555 | 163 | |
b8018e5c JW |
164 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
165 | // 3545. std::pointer_traits should be SFINAE-friendly | |
166 | template<typename _Ptr> | |
167 | struct __ptr_traits_impl<_Ptr, __undefined> | |
168 | { }; | |
4f44c555 | 169 | |
b8018e5c JW |
170 | /** |
171 | * @brief Uniform interface to all pointer-like types | |
757146fb | 172 | * @headerfile memory |
b8018e5c JW |
173 | * @ingroup pointer_abstractions |
174 | * @since C++11 | |
175 | */ | |
176 | template<typename _Ptr> | |
177 | struct pointer_traits : __ptr_traits_impl<_Ptr, __ptr_traits_elem_t<_Ptr>> | |
178 | { }; | |
179 | ||
45ba8f9f JW |
180 | /** |
181 | * @brief Partial specialization for built-in pointers. | |
757146fb | 182 | * @headerfile memory |
45ba8f9f | 183 | * @ingroup pointer_abstractions |
b8018e5c | 184 | * @since C++11 |
45ba8f9f JW |
185 | */ |
186 | template<typename _Tp> | |
b8018e5c | 187 | struct pointer_traits<_Tp*> : __ptr_traits_ptr_to<_Tp*, _Tp> |
45ba8f9f JW |
188 | { |
189 | /// The pointer type | |
190 | typedef _Tp* pointer; | |
191 | /// The type pointed to | |
192 | typedef _Tp element_type; | |
193 | /// Type used to represent the difference between two pointers | |
194 | typedef ptrdiff_t difference_type; | |
b8018e5c JW |
195 | /// A pointer to a different type. |
196 | template<typename _Up> using rebind = _Up*; | |
45ba8f9f JW |
197 | }; |
198 | ||
4f44c555 JW |
199 | /// Convenience alias for rebinding pointers. |
200 | template<typename _Ptr, typename _Tp> | |
201 | using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>; | |
202 | ||
2af96386 JW |
203 | template<typename _Tp> |
204 | constexpr _Tp* | |
205 | __to_address(_Tp* __ptr) noexcept | |
6b590c7a GJF |
206 | { |
207 | static_assert(!std::is_function<_Tp>::value, "not a function pointer"); | |
208 | return __ptr; | |
209 | } | |
2af96386 | 210 | |
7ffa63df | 211 | #ifndef __glibcxx_to_address // C++ < 20 |
2af96386 JW |
212 | template<typename _Ptr> |
213 | constexpr typename std::pointer_traits<_Ptr>::element_type* | |
214 | __to_address(const _Ptr& __ptr) | |
215 | { return std::__to_address(__ptr.operator->()); } | |
61cd19e6 GJF |
216 | #else |
217 | template<typename _Ptr> | |
218 | constexpr auto | |
219 | __to_address(const _Ptr& __ptr) noexcept | |
220 | -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) | |
221 | { return std::pointer_traits<_Ptr>::to_address(__ptr); } | |
222 | ||
223 | template<typename _Ptr, typename... _None> | |
224 | constexpr auto | |
225 | __to_address(const _Ptr& __ptr, _None...) noexcept | |
24fe8c8e JW |
226 | { |
227 | if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>) | |
228 | return std::__to_address(__ptr.base().operator->()); | |
229 | else | |
230 | return std::__to_address(__ptr.operator->()); | |
231 | } | |
61cd19e6 GJF |
232 | |
233 | /** | |
234 | * @brief Obtain address referenced by a pointer to an object | |
235 | * @param __ptr A pointer to an object | |
236 | * @return @c __ptr | |
237 | * @ingroup pointer_abstractions | |
238 | */ | |
239 | template<typename _Tp> | |
240 | constexpr _Tp* | |
241 | to_address(_Tp* __ptr) noexcept | |
6b590c7a | 242 | { return std::__to_address(__ptr); } |
61cd19e6 GJF |
243 | |
244 | /** | |
245 | * @brief Obtain address referenced by a pointer to an object | |
246 | * @param __ptr A pointer to an object | |
247 | * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is | |
248 | well-formed, otherwise @c to_address(__ptr.operator->()) | |
249 | * @ingroup pointer_abstractions | |
250 | */ | |
251 | template<typename _Ptr> | |
252 | constexpr auto | |
253 | to_address(const _Ptr& __ptr) noexcept | |
254 | { return std::__to_address(__ptr); } | |
7ffa63df | 255 | #endif // __glibcxx_to_address |
2af96386 | 256 | |
45ba8f9f JW |
257 | _GLIBCXX_END_NAMESPACE_VERSION |
258 | } // namespace std | |
259 | ||
260 | #endif | |
261 | ||
262 | #endif |