Line data Source code
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
39 : namespace __gnu_debug { struct _Safe_iterator_base; }
40 : #endif
41 :
42 : namespace 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 852 : pointer_to(__make_not_void<element_type>& __r) noexcept
150 852 : { 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 124261 : __to_address(_Tp* __ptr) noexcept
160 : {
161 : static_assert(!std::is_function<_Tp>::value, "not a function pointer");
162 124261 : 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
|