xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/bits/ptr_traits.h (revision 0a3071956a3a9fdebdbf7f338cf2d439b45fc728)
1 // Pointer Traits -*- C++ -*-
2 
3 // Copyright (C) 2011-2022 Free Software Foundation, Inc.
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 
33 #if __cplusplus >= 201103L
34 
35 #include <bits/move.h>
36 
37 #if __cplusplus > 201703L
38 #include <concepts>
39 # ifndef __cpp_lib_constexpr_memory
40 // Defined to a newer value in bits/unique_ptr.h for C++23
41 #  define __cpp_lib_constexpr_memory 201811L
42 # endif
43 namespace __gnu_debug { struct _Safe_iterator_base; }
44 #endif
45 
_GLIBCXX_VISIBILITY(default)46 namespace std _GLIBCXX_VISIBILITY(default)
47 {
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
49 
50   /// @cond undocumented
51 
52   class __undefined;
53 
54   // For a specialization `SomeTemplate<T, Types...>` the member `type` is T,
55   // otherwise `type` is `__undefined`.
56   template<typename _Tp>
57     struct __get_first_arg
58     { using type = __undefined; };
59 
60   template<template<typename, typename...> class _SomeTemplate, typename _Tp,
61            typename... _Types>
62     struct __get_first_arg<_SomeTemplate<_Tp, _Types...>>
63     { using type = _Tp; };
64 
65   // For a specialization `SomeTemplate<T, Args...>` and a type `U` the member
66   // `type` is `SomeTemplate<U, Args...>`, otherwise there is no member `type`.
67   template<typename _Tp, typename _Up>
68     struct __replace_first_arg
69     { };
70 
71   template<template<typename, typename...> class _SomeTemplate, typename _Up,
72            typename _Tp, typename... _Types>
73     struct __replace_first_arg<_SomeTemplate<_Tp, _Types...>, _Up>
74     { using type = _SomeTemplate<_Up, _Types...>; };
75 
76   // Detect the element type of a pointer-like type.
77   template<typename _Ptr, typename = void>
78     struct __ptr_traits_elem : __get_first_arg<_Ptr>
79     { };
80 
81   // Use _Ptr::element_type if is a valid type.
82 #if __cpp_concepts
83   template<typename _Ptr> requires requires { typename _Ptr::element_type; }
84     struct __ptr_traits_elem<_Ptr, void>
85     { using type = typename _Ptr::element_type; };
86 #else
87   template<typename _Ptr>
88     struct __ptr_traits_elem<_Ptr, __void_t<typename _Ptr::element_type>>
89     { using type = typename _Ptr::element_type; };
90 #endif
91 
92   template<typename _Ptr>
93     using __ptr_traits_elem_t = typename __ptr_traits_elem<_Ptr>::type;
94 
95   /// @endcond
96 
97   // Define pointer_traits<P>::pointer_to.
98   template<typename _Ptr, typename _Elt, bool = is_void<_Elt>::value>
99     struct __ptr_traits_ptr_to
100     {
101       using pointer = _Ptr;
102       using element_type = _Elt;
103 
104       /**
105        *  @brief  Obtain a pointer to an object
106        *  @param  __r  A reference to an object of type `element_type`
107        *  @return `pointer::pointer_to(__r)`
108        *  @pre `pointer::pointer_to(__r)` is a valid expression.
109       */
110       static pointer
111       pointer_to(element_type& __r)
112 #if __cpp_lib_concepts
113       requires requires {
114 	{ pointer::pointer_to(__r) } -> convertible_to<pointer>;
115       }
116 #endif
117       { return pointer::pointer_to(__r); }
118     };
119 
120   // Do not define pointer_traits<P>::pointer_to if element type is void.
121   template<typename _Ptr, typename _Elt>
122     struct __ptr_traits_ptr_to<_Ptr, _Elt, true>
123     { };
124 
125   // Partial specialization defining pointer_traits<T*>::pointer_to(T&).
126   template<typename _Tp>
127     struct __ptr_traits_ptr_to<_Tp*, _Tp, false>
128     {
129       using pointer = _Tp*;
130       using element_type = _Tp;
131 
132       /**
133        *  @brief  Obtain a pointer to an object
134        *  @param  __r  A reference to an object of type `element_type`
135        *  @return `addressof(__r)`
136       */
137       static _GLIBCXX20_CONSTEXPR pointer
138       pointer_to(element_type& __r) noexcept
139       { return std::addressof(__r); }
140     };
141 
142   template<typename _Ptr, typename _Elt>
143     struct __ptr_traits_impl : __ptr_traits_ptr_to<_Ptr, _Elt>
144     {
145     private:
146       template<typename _Tp>
147 	using __diff_t = typename _Tp::difference_type;
148 
149       template<typename _Tp, typename _Up>
150 	using __rebind = __type_identity<typename _Tp::template rebind<_Up>>;
151 
152     public:
153       /// The pointer type.
154       using pointer = _Ptr;
155 
156       /// The type pointed to.
157       using element_type = _Elt;
158 
159       /// The type used to represent the difference between two pointers.
160       using difference_type = __detected_or_t<ptrdiff_t, __diff_t, _Ptr>;
161 
162       /// A pointer to a different type.
163       template<typename _Up>
164 	using rebind = typename __detected_or_t<__replace_first_arg<_Ptr, _Up>,
165 						__rebind, _Ptr, _Up>::type;
166     };
167 
168   // _GLIBCXX_RESOLVE_LIB_DEFECTS
169   // 3545. std::pointer_traits should be SFINAE-friendly
170   template<typename _Ptr>
171     struct __ptr_traits_impl<_Ptr, __undefined>
172     { };
173 
174   /**
175    * @brief  Uniform interface to all pointer-like types
176    * @headerfile memory
177    * @ingroup pointer_abstractions
178    * @since C++11
179   */
180   template<typename _Ptr>
181     struct pointer_traits : __ptr_traits_impl<_Ptr, __ptr_traits_elem_t<_Ptr>>
182     { };
183 
184   /**
185    * @brief  Partial specialization for built-in pointers.
186    * @headerfile memory
187    * @ingroup pointer_abstractions
188    * @since C++11
189   */
190   template<typename _Tp>
191     struct pointer_traits<_Tp*> : __ptr_traits_ptr_to<_Tp*, _Tp>
192     {
193       /// The pointer type
194       typedef _Tp* pointer;
195       /// The type pointed to
196       typedef _Tp  element_type;
197       /// Type used to represent the difference between two pointers
198       typedef ptrdiff_t difference_type;
199       /// A pointer to a different type.
200       template<typename _Up> using rebind = _Up*;
201     };
202 
203   /// Convenience alias for rebinding pointers.
204   template<typename _Ptr, typename _Tp>
205     using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>;
206 
207   template<typename _Tp>
208     constexpr _Tp*
209     __to_address(_Tp* __ptr) noexcept
210     {
211       static_assert(!std::is_function<_Tp>::value, "not a function pointer");
212       return __ptr;
213     }
214 
215 #if __cplusplus <= 201703L
216   template<typename _Ptr>
217     constexpr typename std::pointer_traits<_Ptr>::element_type*
218     __to_address(const _Ptr& __ptr)
219     { return std::__to_address(__ptr.operator->()); }
220 #else
221   template<typename _Ptr>
222     constexpr auto
223     __to_address(const _Ptr& __ptr) noexcept
224     -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr))
225     { return std::pointer_traits<_Ptr>::to_address(__ptr); }
226 
227   template<typename _Ptr, typename... _None>
228     constexpr auto
229     __to_address(const _Ptr& __ptr, _None...) noexcept
230     {
231       if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>)
232 	return std::__to_address(__ptr.base().operator->());
233       else
234 	return std::__to_address(__ptr.operator->());
235     }
236 
237 #define __cpp_lib_to_address 201711L
238 
239   /**
240    * @brief Obtain address referenced by a pointer to an object
241    * @param __ptr A pointer to an object
242    * @return @c __ptr
243    * @ingroup pointer_abstractions
244   */
245   template<typename _Tp>
246     constexpr _Tp*
247     to_address(_Tp* __ptr) noexcept
248     { return std::__to_address(__ptr); }
249 
250   /**
251    * @brief Obtain address referenced by a pointer to an object
252    * @param __ptr A pointer to an object
253    * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is
254              well-formed, otherwise @c to_address(__ptr.operator->())
255    * @ingroup pointer_abstractions
256   */
257   template<typename _Ptr>
258     constexpr auto
259     to_address(const _Ptr& __ptr) noexcept
260     { return std::__to_address(__ptr); }
261 #endif // C++2a
262 
263 _GLIBCXX_END_NAMESPACE_VERSION
264 } // namespace std
265 
266 #endif
267 
268 #endif
269