1 // Pointer Traits -*- C++ -*-
3 // Copyright (C) 2011-2024 Free Software Foundation, Inc.
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)
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.
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.
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/>.
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}
31 #define _PTR_TRAITS_H 1
33 #if __cplusplus >= 201103L
35 #include <bits/move.h>
37 #if __cplusplus > 201703L
39 namespace __gnu_debug
{ struct _Safe_iterator_base
; }
42 namespace std
_GLIBCXX_VISIBILITY(default)
44 _GLIBCXX_BEGIN_NAMESPACE_VERSION
46 /// @cond undocumented
50 // For a specialization `SomeTemplate<T, Types...>` the member `type` is T,
51 // otherwise `type` is `__undefined`.
52 template<typename _Tp
>
53 struct __get_first_arg
54 { using type
= __undefined
; };
56 template<template<typename
, typename
...> class _SomeTemplate
, typename _Tp
,
58 struct __get_first_arg
<_SomeTemplate
<_Tp
, _Types
...>>
59 { using type
= _Tp
; };
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`.
63 template<typename _Tp
, typename _Up
>
64 struct __replace_first_arg
67 template<template<typename
, typename
...> class _SomeTemplate
, typename _Up
,
68 typename _Tp
, typename
... _Types
>
69 struct __replace_first_arg
<_SomeTemplate
<_Tp
, _Types
...>, _Up
>
70 { using type
= _SomeTemplate
<_Up
, _Types
...>; };
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
>
77 // Use _Ptr::element_type if is a valid type.
79 template<typename _Ptr
> requires requires
{ typename
_Ptr::element_type
; }
80 struct __ptr_traits_elem
<_Ptr
, void>
81 { using type
= typename
_Ptr::element_type
; };
83 template<typename _Ptr
>
84 struct __ptr_traits_elem
<_Ptr
, __void_t
<typename
_Ptr::element_type
>>
85 { using type
= typename
_Ptr::element_type
; };
88 template<typename _Ptr
>
89 using __ptr_traits_elem_t
= typename __ptr_traits_elem
<_Ptr
>::type
;
93 // Define pointer_traits<P>::pointer_to.
94 template<typename _Ptr
, typename _Elt
, bool = is_void
<_Elt
>::value
>
95 struct __ptr_traits_ptr_to
98 using element_type
= _Elt
;
101 * @brief Obtain a pointer to an object
102 * @param __r A reference to an object of type `element_type`
103 * @return `pointer::pointer_to(__r)`
104 * @pre `pointer::pointer_to(__r)` is a valid expression.
107 pointer_to(element_type
& __r
)
108 #if __cpp_lib_concepts
110 { pointer::pointer_to(__r
) } -> convertible_to
<pointer
>;
113 { return pointer::pointer_to(__r
); }
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>
121 // Partial specialization defining pointer_traits<T*>::pointer_to(T&).
122 template<typename _Tp
>
123 struct __ptr_traits_ptr_to
<_Tp
*, _Tp
, false>
125 using pointer
= _Tp
*;
126 using element_type
= _Tp
;
129 * @brief Obtain a pointer to an object
130 * @param __r A reference to an object of type `element_type`
131 * @return `addressof(__r)`
133 static _GLIBCXX20_CONSTEXPR pointer
134 pointer_to(element_type
& __r
) noexcept
135 { return std::addressof(__r
); }
138 template<typename _Ptr
, typename _Elt
>
139 struct __ptr_traits_impl
: __ptr_traits_ptr_to
<_Ptr
, _Elt
>
142 template<typename _Tp
>
143 using __diff_t
= typename
_Tp::difference_type
;
145 template<typename _Tp
, typename _Up
>
146 using __rebind
= __type_identity
<typename
_Tp::template rebind
<_Up
>>;
149 /// The pointer type.
150 using pointer
= _Ptr
;
152 /// The type pointed to.
153 using element_type
= _Elt
;
155 /// The type used to represent the difference between two pointers.
156 using difference_type
= __detected_or_t
<ptrdiff_t, __diff_t
, _Ptr
>;
158 /// A pointer to a different type.
159 template<typename _Up
>
160 using rebind
= typename __detected_or_t
<__replace_first_arg
<_Ptr
, _Up
>,
161 __rebind
, _Ptr
, _Up
>::type
;
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
>
171 * @brief Uniform interface to all pointer-like types
173 * @ingroup pointer_abstractions
176 template<typename _Ptr
>
177 struct pointer_traits
: __ptr_traits_impl
<_Ptr
, __ptr_traits_elem_t
<_Ptr
>>
181 * @brief Partial specialization for built-in pointers.
183 * @ingroup pointer_abstractions
186 template<typename _Tp
>
187 struct pointer_traits
<_Tp
*> : __ptr_traits_ptr_to
<_Tp
*, _Tp
>
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
;
195 /// A pointer to a different type.
196 template<typename _Up
> using rebind
= _Up
*;
199 /// Convenience alias for rebinding pointers.
200 template<typename _Ptr
, typename _Tp
>
201 using __ptr_rebind
= typename pointer_traits
<_Ptr
>::template rebind
<_Tp
>;
203 #ifndef __glibcxx_to_address // C++ < 20
204 template<typename _Tp
>
205 [[__gnu__::__always_inline__
]]
207 __to_address(_Tp
* __ptr
) noexcept
209 static_assert(!std::is_function
<_Tp
>::value
, "std::to_address argument "
210 "must not be a function pointer");
214 template<typename _Ptr
>
215 constexpr typename
std::pointer_traits
<_Ptr
>::element_type
*
216 __to_address(const _Ptr
& __ptr
)
217 { return std::__to_address(__ptr
.operator->()); }
220 * @brief Obtain address referenced by a pointer to an object
221 * @param __ptr A pointer to an object
223 * @ingroup pointer_abstractions
225 template<typename _Tp
>
226 [[__gnu__::__always_inline__
]]
228 to_address(_Tp
* __ptr
) noexcept
230 static_assert(!is_function_v
<_Tp
>, "std::to_address argument "
231 "must not be a function pointer");
236 * @brief Obtain address referenced by a pointer to an object
237 * @param __ptr A pointer to an object
238 * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is
239 well-formed, otherwise @c to_address(__ptr.operator->())
240 * @ingroup pointer_abstractions
242 template<typename _Ptr
>
244 to_address(const _Ptr
& __ptr
) noexcept
246 if constexpr (requires
{ pointer_traits
<_Ptr
>::to_address(__ptr
); })
247 return pointer_traits
<_Ptr
>::to_address(__ptr
);
248 else if constexpr (is_base_of_v
<__gnu_debug::_Safe_iterator_base
, _Ptr
>)
249 return std::to_address(__ptr
.base().operator->());
251 return std::to_address(__ptr
.operator->());
254 /// @cond undocumented
255 /// Compatibility for use in code that is also compiled as pre-C++20.
256 template<typename _Ptr
>
257 [[__gnu__::__always_inline__
]]
259 __to_address(const _Ptr
& __ptr
) noexcept
260 { return std::to_address(__ptr
); }
262 #endif // __glibcxx_to_address
264 _GLIBCXX_END_NAMESPACE_VERSION