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