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