xref: /llvm-project/libcxx/include/__cxx03/__memory/pointer_traits.h (revision ce7771902dc50d900de639d499a60486b83f70e0)
1e78f53d1SNikolas Klauser // -*- C++ -*-
2e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===//
3e78f53d1SNikolas Klauser //
4e78f53d1SNikolas Klauser // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5e78f53d1SNikolas Klauser // See https://llvm.org/LICENSE.txt for license information.
6e78f53d1SNikolas Klauser // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7e78f53d1SNikolas Klauser //
8e78f53d1SNikolas Klauser //===----------------------------------------------------------------------===//
9e78f53d1SNikolas Klauser 
10*ce777190SNikolas Klauser #ifndef _LIBCPP___CXX03___MEMORY_POINTER_TRAITS_H
11*ce777190SNikolas Klauser #define _LIBCPP___CXX03___MEMORY_POINTER_TRAITS_H
12e78f53d1SNikolas Klauser 
1373fbae83SNikolas Klauser #include <__cxx03/__config>
1473fbae83SNikolas Klauser #include <__cxx03/__memory/addressof.h>
1573fbae83SNikolas Klauser #include <__cxx03/__type_traits/conditional.h>
1673fbae83SNikolas Klauser #include <__cxx03/__type_traits/conjunction.h>
1773fbae83SNikolas Klauser #include <__cxx03/__type_traits/decay.h>
1873fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_class.h>
1973fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_function.h>
2073fbae83SNikolas Klauser #include <__cxx03/__type_traits/is_void.h>
2173fbae83SNikolas Klauser #include <__cxx03/__type_traits/void_t.h>
2273fbae83SNikolas Klauser #include <__cxx03/__utility/declval.h>
2373fbae83SNikolas Klauser #include <__cxx03/__utility/forward.h>
2473fbae83SNikolas Klauser #include <__cxx03/cstddef>
25e78f53d1SNikolas Klauser 
26e78f53d1SNikolas Klauser #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
27e78f53d1SNikolas Klauser #  pragma GCC system_header
28e78f53d1SNikolas Klauser #endif
29e78f53d1SNikolas Klauser 
30e78f53d1SNikolas Klauser _LIBCPP_PUSH_MACROS
3173fbae83SNikolas Klauser #include <__cxx03/__undef_macros>
32e78f53d1SNikolas Klauser 
33e78f53d1SNikolas Klauser _LIBCPP_BEGIN_NAMESPACE_STD
34e78f53d1SNikolas Klauser 
35e78f53d1SNikolas Klauser // clang-format off
36e78f53d1SNikolas Klauser #define _LIBCPP_CLASS_TRAITS_HAS_XXX(NAME, PROPERTY)                                                                   \
37e78f53d1SNikolas Klauser   template <class _Tp, class = void>                                                                                   \
38e78f53d1SNikolas Klauser   struct NAME : false_type {};                                                                                         \
39e78f53d1SNikolas Klauser   template <class _Tp>                                                                                                 \
40e78f53d1SNikolas Klauser   struct NAME<_Tp, __void_t<typename _Tp::PROPERTY> > : true_type {}
41e78f53d1SNikolas Klauser // clang-format on
42e78f53d1SNikolas Klauser 
43e78f53d1SNikolas Klauser _LIBCPP_CLASS_TRAITS_HAS_XXX(__has_pointer, pointer);
44e78f53d1SNikolas Klauser _LIBCPP_CLASS_TRAITS_HAS_XXX(__has_element_type, element_type);
45e78f53d1SNikolas Klauser 
46e78f53d1SNikolas Klauser template <class _Ptr, bool = __has_element_type<_Ptr>::value>
47e78f53d1SNikolas Klauser struct __pointer_traits_element_type {};
48e78f53d1SNikolas Klauser 
49e78f53d1SNikolas Klauser template <class _Ptr>
50e78f53d1SNikolas Klauser struct __pointer_traits_element_type<_Ptr, true> {
51e78f53d1SNikolas Klauser   typedef _LIBCPP_NODEBUG typename _Ptr::element_type type;
52e78f53d1SNikolas Klauser };
53e78f53d1SNikolas Klauser 
54e78f53d1SNikolas Klauser template <template <class, class...> class _Sp, class _Tp, class... _Args>
55e78f53d1SNikolas Klauser struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, true> {
56e78f53d1SNikolas Klauser   typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::element_type type;
57e78f53d1SNikolas Klauser };
58e78f53d1SNikolas Klauser 
59e78f53d1SNikolas Klauser template <template <class, class...> class _Sp, class _Tp, class... _Args>
60e78f53d1SNikolas Klauser struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, false> {
61e78f53d1SNikolas Klauser   typedef _LIBCPP_NODEBUG _Tp type;
62e78f53d1SNikolas Klauser };
63e78f53d1SNikolas Klauser 
64e78f53d1SNikolas Klauser template <class _Tp, class = void>
65e78f53d1SNikolas Klauser struct __has_difference_type : false_type {};
66e78f53d1SNikolas Klauser 
67e78f53d1SNikolas Klauser template <class _Tp>
68e78f53d1SNikolas Klauser struct __has_difference_type<_Tp, __void_t<typename _Tp::difference_type> > : true_type {};
69e78f53d1SNikolas Klauser 
70e78f53d1SNikolas Klauser template <class _Ptr, bool = __has_difference_type<_Ptr>::value>
71e78f53d1SNikolas Klauser struct __pointer_traits_difference_type {
72e78f53d1SNikolas Klauser   typedef _LIBCPP_NODEBUG ptrdiff_t type;
73e78f53d1SNikolas Klauser };
74e78f53d1SNikolas Klauser 
75e78f53d1SNikolas Klauser template <class _Ptr>
76e78f53d1SNikolas Klauser struct __pointer_traits_difference_type<_Ptr, true> {
77e78f53d1SNikolas Klauser   typedef _LIBCPP_NODEBUG typename _Ptr::difference_type type;
78e78f53d1SNikolas Klauser };
79e78f53d1SNikolas Klauser 
80e78f53d1SNikolas Klauser template <class _Tp, class _Up>
81e78f53d1SNikolas Klauser struct __has_rebind {
82e78f53d1SNikolas Klauser private:
83e78f53d1SNikolas Klauser   template <class _Xp>
84e78f53d1SNikolas Klauser   static false_type __test(...);
85e78f53d1SNikolas Klauser   _LIBCPP_SUPPRESS_DEPRECATED_PUSH
86e78f53d1SNikolas Klauser   template <class _Xp>
87e78f53d1SNikolas Klauser   static true_type __test(typename _Xp::template rebind<_Up>* = 0);
88e78f53d1SNikolas Klauser   _LIBCPP_SUPPRESS_DEPRECATED_POP
89e78f53d1SNikolas Klauser 
90e78f53d1SNikolas Klauser public:
91e78f53d1SNikolas Klauser   static const bool value = decltype(__test<_Tp>(0))::value;
92e78f53d1SNikolas Klauser };
93e78f53d1SNikolas Klauser 
94e78f53d1SNikolas Klauser template <class _Tp, class _Up, bool = __has_rebind<_Tp, _Up>::value>
95e78f53d1SNikolas Klauser struct __pointer_traits_rebind {
96e78f53d1SNikolas Klauser #ifndef _LIBCPP_CXX03_LANG
97e78f53d1SNikolas Klauser   typedef _LIBCPP_NODEBUG typename _Tp::template rebind<_Up> type;
98e78f53d1SNikolas Klauser #else
99e78f53d1SNikolas Klauser   typedef _LIBCPP_NODEBUG typename _Tp::template rebind<_Up>::other type;
100e78f53d1SNikolas Klauser #endif
101e78f53d1SNikolas Klauser };
102e78f53d1SNikolas Klauser 
103e78f53d1SNikolas Klauser template <template <class, class...> class _Sp, class _Tp, class... _Args, class _Up>
104e78f53d1SNikolas Klauser struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, true> {
105e78f53d1SNikolas Klauser #ifndef _LIBCPP_CXX03_LANG
106e78f53d1SNikolas Klauser   typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::template rebind<_Up> type;
107e78f53d1SNikolas Klauser #else
108e78f53d1SNikolas Klauser   typedef _LIBCPP_NODEBUG typename _Sp<_Tp, _Args...>::template rebind<_Up>::other type;
109e78f53d1SNikolas Klauser #endif
110e78f53d1SNikolas Klauser };
111e78f53d1SNikolas Klauser 
112e78f53d1SNikolas Klauser template <template <class, class...> class _Sp, class _Tp, class... _Args, class _Up>
113e78f53d1SNikolas Klauser struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false> {
114e78f53d1SNikolas Klauser   typedef _Sp<_Up, _Args...> type;
115e78f53d1SNikolas Klauser };
116e78f53d1SNikolas Klauser 
117e78f53d1SNikolas Klauser template <class _Ptr, class = void>
118e78f53d1SNikolas Klauser struct __pointer_traits_impl {};
119e78f53d1SNikolas Klauser 
120e78f53d1SNikolas Klauser template <class _Ptr>
121e78f53d1SNikolas Klauser struct __pointer_traits_impl<_Ptr, __void_t<typename __pointer_traits_element_type<_Ptr>::type> > {
122e78f53d1SNikolas Klauser   typedef _Ptr pointer;
123e78f53d1SNikolas Klauser   typedef typename __pointer_traits_element_type<pointer>::type element_type;
124e78f53d1SNikolas Klauser   typedef typename __pointer_traits_difference_type<pointer>::type difference_type;
125e78f53d1SNikolas Klauser 
126e78f53d1SNikolas Klauser #ifndef _LIBCPP_CXX03_LANG
127e78f53d1SNikolas Klauser   template <class _Up>
128e78f53d1SNikolas Klauser   using rebind = typename __pointer_traits_rebind<pointer, _Up>::type;
129e78f53d1SNikolas Klauser #else
130e78f53d1SNikolas Klauser   template <class _Up>
131e78f53d1SNikolas Klauser   struct rebind {
132e78f53d1SNikolas Klauser     typedef typename __pointer_traits_rebind<pointer, _Up>::type other;
133e78f53d1SNikolas Klauser   };
134e78f53d1SNikolas Klauser #endif // _LIBCPP_CXX03_LANG
135e78f53d1SNikolas Klauser 
136e78f53d1SNikolas Klauser private:
137e78f53d1SNikolas Klauser   struct __nat {};
138e78f53d1SNikolas Klauser 
139e78f53d1SNikolas Klauser public:
140e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer
141e78f53d1SNikolas Klauser   pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) {
142e78f53d1SNikolas Klauser     return pointer::pointer_to(__r);
143e78f53d1SNikolas Klauser   }
144e78f53d1SNikolas Klauser };
145e78f53d1SNikolas Klauser 
146e78f53d1SNikolas Klauser template <class _Ptr>
147e78f53d1SNikolas Klauser struct _LIBCPP_TEMPLATE_VIS pointer_traits : __pointer_traits_impl<_Ptr> {};
148e78f53d1SNikolas Klauser 
149e78f53d1SNikolas Klauser template <class _Tp>
150e78f53d1SNikolas Klauser struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*> {
151e78f53d1SNikolas Klauser   typedef _Tp* pointer;
152e78f53d1SNikolas Klauser   typedef _Tp element_type;
153e78f53d1SNikolas Klauser   typedef ptrdiff_t difference_type;
154e78f53d1SNikolas Klauser 
155e78f53d1SNikolas Klauser #ifndef _LIBCPP_CXX03_LANG
156e78f53d1SNikolas Klauser   template <class _Up>
157e78f53d1SNikolas Klauser   using rebind = _Up*;
158e78f53d1SNikolas Klauser #else
159e78f53d1SNikolas Klauser   template <class _Up>
160e78f53d1SNikolas Klauser   struct rebind {
161e78f53d1SNikolas Klauser     typedef _Up* other;
162e78f53d1SNikolas Klauser   };
163e78f53d1SNikolas Klauser #endif
164e78f53d1SNikolas Klauser 
165e78f53d1SNikolas Klauser private:
166e78f53d1SNikolas Klauser   struct __nat {};
167e78f53d1SNikolas Klauser 
168e78f53d1SNikolas Klauser public:
169e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 static pointer
170e78f53d1SNikolas Klauser   pointer_to(__conditional_t<is_void<element_type>::value, __nat, element_type>& __r) _NOEXCEPT {
171e78f53d1SNikolas Klauser     return std::addressof(__r);
172e78f53d1SNikolas Klauser   }
173e78f53d1SNikolas Klauser };
174e78f53d1SNikolas Klauser 
175e78f53d1SNikolas Klauser #ifndef _LIBCPP_CXX03_LANG
176e78f53d1SNikolas Klauser template <class _From, class _To>
177e78f53d1SNikolas Klauser using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>;
178e78f53d1SNikolas Klauser #else
179e78f53d1SNikolas Klauser template <class _From, class _To>
180e78f53d1SNikolas Klauser using __rebind_pointer_t = typename pointer_traits<_From>::template rebind<_To>::other;
181e78f53d1SNikolas Klauser #endif
182e78f53d1SNikolas Klauser 
183e78f53d1SNikolas Klauser // to_address
184e78f53d1SNikolas Klauser 
185e78f53d1SNikolas Klauser template <class _Pointer, class = void>
186e78f53d1SNikolas Klauser struct __to_address_helper;
187e78f53d1SNikolas Klauser 
188e78f53d1SNikolas Klauser template <class _Tp>
189e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* __to_address(_Tp* __p) _NOEXCEPT {
190e78f53d1SNikolas Klauser   static_assert(!is_function<_Tp>::value, "_Tp is a function type");
191e78f53d1SNikolas Klauser   return __p;
192e78f53d1SNikolas Klauser }
193e78f53d1SNikolas Klauser 
194e78f53d1SNikolas Klauser template <class _Pointer, class = void>
195e78f53d1SNikolas Klauser struct _HasToAddress : false_type {};
196e78f53d1SNikolas Klauser 
197e78f53d1SNikolas Klauser template <class _Pointer>
198e78f53d1SNikolas Klauser struct _HasToAddress<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>())) >
199e78f53d1SNikolas Klauser     : true_type {};
200e78f53d1SNikolas Klauser 
201e78f53d1SNikolas Klauser template <class _Pointer, class = void>
202e78f53d1SNikolas Klauser struct _HasArrow : false_type {};
203e78f53d1SNikolas Klauser 
204e78f53d1SNikolas Klauser template <class _Pointer>
205e78f53d1SNikolas Klauser struct _HasArrow<_Pointer, decltype((void)std::declval<const _Pointer&>().operator->()) > : true_type {};
206e78f53d1SNikolas Klauser 
207e78f53d1SNikolas Klauser template <class _Pointer>
208e78f53d1SNikolas Klauser struct _IsFancyPointer {
209e78f53d1SNikolas Klauser   static const bool value = _HasArrow<_Pointer>::value || _HasToAddress<_Pointer>::value;
210e78f53d1SNikolas Klauser };
211e78f53d1SNikolas Klauser 
212e78f53d1SNikolas Klauser // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers
213e78f53d1SNikolas Klauser template <class _Pointer, __enable_if_t< _And<is_class<_Pointer>, _IsFancyPointer<_Pointer> >::value, int> = 0>
214e78f53d1SNikolas Klauser _LIBCPP_HIDE_FROM_ABI
215e78f53d1SNikolas Klauser _LIBCPP_CONSTEXPR __decay_t<decltype(__to_address_helper<_Pointer>::__call(std::declval<const _Pointer&>()))>
216e78f53d1SNikolas Klauser __to_address(const _Pointer& __p) _NOEXCEPT {
217e78f53d1SNikolas Klauser   return __to_address_helper<_Pointer>::__call(__p);
218e78f53d1SNikolas Klauser }
219e78f53d1SNikolas Klauser 
220e78f53d1SNikolas Klauser template <class _Pointer, class>
221e78f53d1SNikolas Klauser struct __to_address_helper {
222e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI
223e78f53d1SNikolas Klauser   _LIBCPP_CONSTEXPR static decltype(std::__to_address(std::declval<const _Pointer&>().operator->()))
224e78f53d1SNikolas Klauser   __call(const _Pointer& __p) _NOEXCEPT {
225e78f53d1SNikolas Klauser     return std::__to_address(__p.operator->());
226e78f53d1SNikolas Klauser   }
227e78f53d1SNikolas Klauser };
228e78f53d1SNikolas Klauser 
229e78f53d1SNikolas Klauser template <class _Pointer>
230e78f53d1SNikolas Klauser struct __to_address_helper<_Pointer,
231e78f53d1SNikolas Klauser                            decltype((void)pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))> {
232e78f53d1SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI
233e78f53d1SNikolas Klauser   _LIBCPP_CONSTEXPR static decltype(pointer_traits<_Pointer>::to_address(std::declval<const _Pointer&>()))
234e78f53d1SNikolas Klauser   __call(const _Pointer& __p) _NOEXCEPT {
235e78f53d1SNikolas Klauser     return pointer_traits<_Pointer>::to_address(__p);
236e78f53d1SNikolas Klauser   }
237e78f53d1SNikolas Klauser };
238e78f53d1SNikolas Klauser 
239e78f53d1SNikolas Klauser #if _LIBCPP_STD_VER >= 20
240e78f53d1SNikolas Klauser template <class _Tp>
241e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI constexpr auto to_address(_Tp* __p) noexcept {
242e78f53d1SNikolas Klauser   return std::__to_address(__p);
243e78f53d1SNikolas Klauser }
244e78f53d1SNikolas Klauser 
245e78f53d1SNikolas Klauser template <class _Pointer>
246e78f53d1SNikolas Klauser inline _LIBCPP_HIDE_FROM_ABI constexpr auto
247e78f53d1SNikolas Klauser to_address(const _Pointer& __p) noexcept -> decltype(std::__to_address(__p)) {
248e78f53d1SNikolas Klauser   return std::__to_address(__p);
249e78f53d1SNikolas Klauser }
250e78f53d1SNikolas Klauser #endif
251e78f53d1SNikolas Klauser 
252e78f53d1SNikolas Klauser #if _LIBCPP_STD_VER >= 23
253e78f53d1SNikolas Klauser 
254e78f53d1SNikolas Klauser template <class _Tp>
255e78f53d1SNikolas Klauser struct __pointer_of {};
256e78f53d1SNikolas Klauser 
257e78f53d1SNikolas Klauser template <class _Tp>
258e78f53d1SNikolas Klauser   requires(__has_pointer<_Tp>::value)
259e78f53d1SNikolas Klauser struct __pointer_of<_Tp> {
260e78f53d1SNikolas Klauser   using type = typename _Tp::pointer;
261e78f53d1SNikolas Klauser };
262e78f53d1SNikolas Klauser 
263e78f53d1SNikolas Klauser template <class _Tp>
264e78f53d1SNikolas Klauser   requires(!__has_pointer<_Tp>::value && __has_element_type<_Tp>::value)
265e78f53d1SNikolas Klauser struct __pointer_of<_Tp> {
266e78f53d1SNikolas Klauser   using type = typename _Tp::element_type*;
267e78f53d1SNikolas Klauser };
268e78f53d1SNikolas Klauser 
269e78f53d1SNikolas Klauser template <class _Tp>
270e78f53d1SNikolas Klauser   requires(!__has_pointer<_Tp>::value && !__has_element_type<_Tp>::value &&
271e78f53d1SNikolas Klauser            __has_element_type<pointer_traits<_Tp>>::value)
272e78f53d1SNikolas Klauser struct __pointer_of<_Tp> {
273e78f53d1SNikolas Klauser   using type = typename pointer_traits<_Tp>::element_type*;
274e78f53d1SNikolas Klauser };
275e78f53d1SNikolas Klauser 
276e78f53d1SNikolas Klauser template <typename _Tp>
277e78f53d1SNikolas Klauser using __pointer_of_t = typename __pointer_of<_Tp>::type;
278e78f53d1SNikolas Klauser 
279e78f53d1SNikolas Klauser template <class _Tp, class _Up>
280e78f53d1SNikolas Klauser struct __pointer_of_or {
281e78f53d1SNikolas Klauser   using type _LIBCPP_NODEBUG = _Up;
282e78f53d1SNikolas Klauser };
283e78f53d1SNikolas Klauser 
284e78f53d1SNikolas Klauser template <class _Tp, class _Up>
285e78f53d1SNikolas Klauser   requires requires { typename __pointer_of_t<_Tp>; }
286e78f53d1SNikolas Klauser struct __pointer_of_or<_Tp, _Up> {
287e78f53d1SNikolas Klauser   using type _LIBCPP_NODEBUG = __pointer_of_t<_Tp>;
288e78f53d1SNikolas Klauser };
289e78f53d1SNikolas Klauser 
290e78f53d1SNikolas Klauser template <typename _Tp, typename _Up>
291e78f53d1SNikolas Klauser using __pointer_of_or_t = typename __pointer_of_or<_Tp, _Up>::type;
292e78f53d1SNikolas Klauser 
293e78f53d1SNikolas Klauser template <class _Smart>
294e78f53d1SNikolas Klauser concept __resettable_smart_pointer = requires(_Smart __s) { __s.reset(); };
295e78f53d1SNikolas Klauser 
296e78f53d1SNikolas Klauser template <class _Smart, class _Pointer, class... _Args>
297e78f53d1SNikolas Klauser concept __resettable_smart_pointer_with_args = requires(_Smart __s, _Pointer __p, _Args... __args) {
298e78f53d1SNikolas Klauser   __s.reset(static_cast<__pointer_of_or_t<_Smart, _Pointer>>(__p), std::forward<_Args>(__args)...);
299e78f53d1SNikolas Klauser };
300e78f53d1SNikolas Klauser 
301e78f53d1SNikolas Klauser #endif
302e78f53d1SNikolas Klauser 
303e78f53d1SNikolas Klauser _LIBCPP_END_NAMESPACE_STD
304e78f53d1SNikolas Klauser 
305e78f53d1SNikolas Klauser _LIBCPP_POP_MACROS
306e78f53d1SNikolas Klauser 
307*ce777190SNikolas Klauser #endif // _LIBCPP___CXX03___MEMORY_POINTER_TRAITS_H
308