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