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#define __cpp_lib_constexpr_memory 201811L 
39namespace __gnu_debug { struct _Safe_iterator_base; } 
40#endif 
41 
42namespace std _GLIBCXX_VISIBILITY(default
43
44_GLIBCXX_BEGIN_NAMESPACE_VERSION 
45 
46 class __undefined
47 
48 // Given Template<T, ...> and U return Template<U, ...>, otherwise invalid. 
49 template<typename _Tp, typename _Up> 
50 struct __replace_first_arg 
51 { }; 
52 
53 template<template<typename, typename...> class _Template, typename _Up, 
54 typename _Tp, typename... _Types> 
55 struct __replace_first_arg<_Template<_Tp, _Types...>, _Up> 
56 { using type = _Template<_Up, _Types...>; }; 
57 
58 template<typename _Tp, typename _Up> 
59 using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type; 
60 
61 template<typename _Tp> 
62 using __make_not_void 
63 = typename conditional<is_void<_Tp>::value, __undefined, _Tp>::type; 
64 
65 template<typename _Ptr> 
66 struct __ptr_traits_elem_1 
67 { }; 
68 
69 template<template<typename, typename...> class _SomePointer, typename _Tp, 
70 typename... _Args> 
71 struct __ptr_traits_elem_1<_SomePointer<_Tp, _Args...>> 
72
73 using element_type = _Tp; 
74 using pointer = _SomePointer<_Tp, _Args...>; 
75 
76 static pointer 
77 pointer_to(__make_not_void<element_type>& __e
78 { return pointer::pointer_to(__e); } 
79 }; 
80 
81 template<typename _Ptr, typename = void
82 struct __ptr_traits_elem : __ptr_traits_elem_1<_Ptr> 
83 { }; 
84 
85 template<typename _Ptr> 
86 struct __ptr_traits_elem<_Ptr, __void_t<typename _Ptr::element_type>> 
87
88 using element_type = typename _Ptr::element_type; 
89 
90 static _Ptr 
91 pointer_to(__make_not_void<element_type>& __e
92 { return _Ptr::pointer_to(__e); } 
93 }; 
94 
95 /** 
96 * @brief Uniform interface to all pointer-like types 
97 * @ingroup pointer_abstractions 
98 */ 
99 template<typename _Ptr> 
100 struct pointer_traits : __ptr_traits_elem<_Ptr> 
101
102 private
103 template<typename _Tp> 
104 using __difference_type = typename _Tp::difference_type; 
105 
106 template<typename _Tp, typename _Up, typename = void
107 struct __rebind : __replace_first_arg<_Tp, _Up> { }; 
108 
109 template<typename _Tp, typename _Up> 
110 struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>> 
111 { using type = typename _Tp::template rebind<_Up>; }; 
112 
113 public
114 /// The pointer type. 
115 using pointer = _Ptr; 
116 
117 /// The type used to represent the difference between two pointers. 
118 using difference_type 
119 = __detected_or_t<ptrdiff_t, __difference_type, _Ptr>; 
120 
121 /// A pointer to a different type. 
122 template<typename _Up> 
123 using rebind = typename __rebind<_Ptr, _Up>::type; 
124 }; 
125 
126 /** 
127 * @brief Partial specialization for built-in pointers. 
128 * @ingroup pointer_abstractions 
129 */ 
130 template<typename _Tp> 
131 struct pointer_traits<_Tp*> 
132
133 /// The pointer type 
134 typedef _Tp* pointer
135 /// The type pointed to 
136 typedef _Tp element_type
137 /// Type used to represent the difference between two pointers 
138 typedef ptrdiff_t difference_type
139 
140 template<typename _Up> 
141 using rebind = _Up*; 
142 
143 /** 
144 * @brief Obtain a pointer to an object 
145 * @param __r A reference to an object of type @c element_type 
146 * @return @c addressof(__r) 
147 */ 
148 static _GLIBCXX20_CONSTEXPR pointer 
149 pointer_to(__make_not_void<element_type>& __r) noexcept 
150 { return std::addressof(__r); } 
151 }; 
152 
153 /// Convenience alias for rebinding pointers. 
154 template<typename _Ptr, typename _Tp> 
155 using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>; 
156 
157 template<typename _Tp> 
158 constexpr _Tp* 
159 __to_address(_Tp* __ptr) noexcept 
160
161 static_assert(!std::is_function<_Tp>::value, "not a function pointer"); 
162 return __ptr
163
164 
165#if __cplusplus <= 201703L 
166 template<typename _Ptr> 
167 constexpr typename std::pointer_traits<_Ptr>::element_type* 
168 __to_address(const _Ptr& __ptr) 
169 { return std::__to_address(__ptr.operator->()); } 
170#else 
171 
172 template<typename _Ptr> 
173 constexpr auto 
174 __to_address(const _Ptr& __ptr) noexcept 
175 -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) 
176 { return std::pointer_traits<_Ptr>::to_address(__ptr); } 
177 
178 template<typename _Ptr, typename... _None> 
179 constexpr auto 
180 __to_address(const _Ptr& __ptr, _None...) noexcept 
181
182 if constexpr (is_base_of_v<__gnu_debug::_Safe_iterator_base, _Ptr>) 
183 return std::__to_address(__ptr.base().operator->()); 
184 else 
185 return std::__to_address(__ptr.operator->()); 
186
187 
188#define __cpp_lib_to_address 201711L 
189 
190 /** 
191 * @brief Obtain address referenced by a pointer to an object 
192 * @param __ptr A pointer to an object 
193 * @return @c __ptr 
194 * @ingroup pointer_abstractions 
195 */ 
196 template<typename _Tp> 
197 constexpr _Tp* 
198 to_address(_Tp* __ptr) noexcept 
199 { return std::__to_address(__ptr); } 
200 
201 /** 
202 * @brief Obtain address referenced by a pointer to an object 
203 * @param __ptr A pointer to an object 
204 * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is 
205 well-formed, otherwise @c to_address(__ptr.operator->()) 
206 * @ingroup pointer_abstractions 
207 */ 
208 template<typename _Ptr> 
209 constexpr auto 
210 to_address(const _Ptr& __ptr) noexcept 
211 { return std::__to_address(__ptr); } 
212#endif // C++2a 
213 
214_GLIBCXX_END_NAMESPACE_VERSION 
215} // namespace std 
216 
217#endif 
218 
219#endif 
220