libstdc++
ptr_traits.h
Go to the documentation of this file.
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
constexpr auto to_address(const _Ptr &__ptr) noexcept
Obtain address referenced by a pointer to an object.
Definition: ptr_traits.h:278
constexpr _Tp * to_address(_Tp *__ptr) noexcept
Obtain address referenced by a pointer to an object.
Definition: ptr_traits.h:266
constexpr _Tp * addressof(_Tp &__r) noexcept
Returns the actual address of the object or function referenced by r, even in the presence of an over...
Definition: move.h:145
ISO C++ entities toplevel namespace is std.
typename pointer_traits< _Ptr >::template rebind< _Tp > __ptr_rebind
Convenience alias for rebinding pointers.
Definition: ptr_traits.h:224
GNU debug classes for public use.
is_function
Definition: type_traits:541
Uniform interface to all pointer-like types.
Definition: ptr_traits.h:195
_Tp * pointer
The pointer type.
Definition: ptr_traits.h:213
ptrdiff_t difference_type
Type used to represent the difference between two pointers.
Definition: ptr_traits.h:217
_Tp element_type
The type pointed to.
Definition: ptr_traits.h:215
_Up * rebind
A pointer to a different type.
Definition: ptr_traits.h:219