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  /// @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
_Up * rebind
A pointer to a different type.
Definition: ptr_traits.h:200
typename pointer_traits< _Ptr >::template rebind< _Tp > __ptr_rebind
Convenience alias for rebinding pointers.
Definition: ptr_traits.h:205
_Tp * pointer
The pointer type.
Definition: ptr_traits.h:194
ptrdiff_t difference_type
Type used to represent the difference between two pointers.
Definition: ptr_traits.h:198
ISO C++ entities toplevel namespace is std.
_Tp element_type
The type pointed to.
Definition: ptr_traits.h:196
constexpr auto to_address(const _Ptr &__ptr) noexcept
Obtain address referenced by a pointer to an object.
Definition: ptr_traits.h:259
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
is_function
Definition: type_traits:227
Uniform interface to all pointer-like types.
Definition: ptr_traits.h:181
GNU debug classes for public use.