xref: /freebsd/contrib/llvm-project/libcxx/include/__memory/pointer_traits.h (revision 963f5dc7a30624e95d72fb7f87b8892651164e46)
1 // -*- C++ -*-
2 //===----------------------------------------------------------------------===//
3 //
4 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 // See https://llvm.org/LICENSE.txt for license information.
6 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef _LIBCPP___MEMORY_POINTER_TRAITS_H
11 #define _LIBCPP___MEMORY_POINTER_TRAITS_H
12 
13 #include <__config>
14 #include <__memory/addressof.h>
15 #include <type_traits>
16 
17 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
18 #pragma GCC system_header
19 #endif
20 
21 _LIBCPP_PUSH_MACROS
22 #include <__undef_macros>
23 
24 _LIBCPP_BEGIN_NAMESPACE_STD
25 
26 template <class _Tp, class = void>
27 struct __has_element_type : false_type {};
28 
29 template <class _Tp>
30 struct __has_element_type<_Tp,
31               typename __void_t<typename _Tp::element_type>::type> : true_type {};
32 
33 template <class _Ptr, bool = __has_element_type<_Ptr>::value>
34 struct __pointer_traits_element_type;
35 
36 template <class _Ptr>
37 struct __pointer_traits_element_type<_Ptr, true>
38 {
39     typedef _LIBCPP_NODEBUG_TYPE typename _Ptr::element_type type;
40 };
41 
42 template <template <class, class...> class _Sp, class _Tp, class ..._Args>
43 struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, true>
44 {
45     typedef _LIBCPP_NODEBUG_TYPE typename _Sp<_Tp, _Args...>::element_type type;
46 };
47 
48 template <template <class, class...> class _Sp, class _Tp, class ..._Args>
49 struct __pointer_traits_element_type<_Sp<_Tp, _Args...>, false>
50 {
51     typedef _LIBCPP_NODEBUG_TYPE _Tp type;
52 };
53 
54 template <class _Tp, class = void>
55 struct __has_difference_type : false_type {};
56 
57 template <class _Tp>
58 struct __has_difference_type<_Tp,
59             typename __void_t<typename _Tp::difference_type>::type> : true_type {};
60 
61 template <class _Ptr, bool = __has_difference_type<_Ptr>::value>
62 struct __pointer_traits_difference_type
63 {
64     typedef _LIBCPP_NODEBUG_TYPE ptrdiff_t type;
65 };
66 
67 template <class _Ptr>
68 struct __pointer_traits_difference_type<_Ptr, true>
69 {
70     typedef _LIBCPP_NODEBUG_TYPE typename _Ptr::difference_type type;
71 };
72 
73 template <class _Tp, class _Up>
74 struct __has_rebind
75 {
76 private:
77     struct __two {char __lx; char __lxx;};
78     template <class _Xp> static __two __test(...);
79     _LIBCPP_SUPPRESS_DEPRECATED_PUSH
80     template <class _Xp> static char __test(typename _Xp::template rebind<_Up>* = 0);
81     _LIBCPP_SUPPRESS_DEPRECATED_POP
82 public:
83     static const bool value = sizeof(__test<_Tp>(0)) == 1;
84 };
85 
86 template <class _Tp, class _Up, bool = __has_rebind<_Tp, _Up>::value>
87 struct __pointer_traits_rebind
88 {
89 #ifndef _LIBCPP_CXX03_LANG
90     typedef _LIBCPP_NODEBUG_TYPE typename _Tp::template rebind<_Up> type;
91 #else
92     typedef _LIBCPP_NODEBUG_TYPE typename _Tp::template rebind<_Up>::other type;
93 #endif
94 };
95 
96 template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up>
97 struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, true>
98 {
99 #ifndef _LIBCPP_CXX03_LANG
100     typedef _LIBCPP_NODEBUG_TYPE typename _Sp<_Tp, _Args...>::template rebind<_Up> type;
101 #else
102     typedef _LIBCPP_NODEBUG_TYPE typename _Sp<_Tp, _Args...>::template rebind<_Up>::other type;
103 #endif
104 };
105 
106 template <template <class, class...> class _Sp, class _Tp, class ..._Args, class _Up>
107 struct __pointer_traits_rebind<_Sp<_Tp, _Args...>, _Up, false>
108 {
109     typedef _Sp<_Up, _Args...> type;
110 };
111 
112 template <class _Ptr>
113 struct _LIBCPP_TEMPLATE_VIS pointer_traits
114 {
115     typedef _Ptr                                                     pointer;
116     typedef typename __pointer_traits_element_type<pointer>::type    element_type;
117     typedef typename __pointer_traits_difference_type<pointer>::type difference_type;
118 
119 #ifndef _LIBCPP_CXX03_LANG
120     template <class _Up> using rebind = typename __pointer_traits_rebind<pointer, _Up>::type;
121 #else
122     template <class _Up> struct rebind
123         {typedef typename __pointer_traits_rebind<pointer, _Up>::type other;};
124 #endif // _LIBCPP_CXX03_LANG
125 
126 private:
127     struct __nat {};
128 public:
129     _LIBCPP_INLINE_VISIBILITY
130     static pointer pointer_to(typename conditional<is_void<element_type>::value,
131                                            __nat, element_type>::type& __r)
132         {return pointer::pointer_to(__r);}
133 };
134 
135 template <class _Tp>
136 struct _LIBCPP_TEMPLATE_VIS pointer_traits<_Tp*>
137 {
138     typedef _Tp*      pointer;
139     typedef _Tp       element_type;
140     typedef ptrdiff_t difference_type;
141 
142 #ifndef _LIBCPP_CXX03_LANG
143     template <class _Up> using rebind = _Up*;
144 #else
145     template <class _Up> struct rebind {typedef _Up* other;};
146 #endif
147 
148 private:
149     struct __nat {};
150 public:
151     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
152     static pointer pointer_to(typename conditional<is_void<element_type>::value,
153                                       __nat, element_type>::type& __r) _NOEXCEPT
154         {return _VSTD::addressof(__r);}
155 };
156 
157 template <class _From, class _To>
158 struct __rebind_pointer {
159 #ifndef _LIBCPP_CXX03_LANG
160     typedef typename pointer_traits<_From>::template rebind<_To>        type;
161 #else
162     typedef typename pointer_traits<_From>::template rebind<_To>::other type;
163 #endif
164 };
165 
166 // to_address
167 
168 template <class _Pointer, class = void>
169 struct __to_address_helper;
170 
171 template <class _Tp>
172 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
173 _Tp* __to_address(_Tp* __p) _NOEXCEPT {
174     static_assert(!is_function<_Tp>::value, "_Tp is a function type");
175     return __p;
176 }
177 
178 // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers
179 template <class _Pointer, class = _EnableIf<!is_pointer<_Pointer>::value> >
180 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
181 typename decay<decltype(__to_address_helper<_Pointer>::__call(declval<const _Pointer&>()))>::type
182 __to_address(const _Pointer& __p) _NOEXCEPT {
183     return __to_address_helper<_Pointer>::__call(__p);
184 }
185 
186 template <class _Pointer, class>
187 struct __to_address_helper {
188     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
189     static decltype(_VSTD::__to_address(declval<const _Pointer&>().operator->()))
190     __call(const _Pointer&__p) _NOEXCEPT {
191         return _VSTD::__to_address(__p.operator->());
192     }
193 };
194 
195 template <class _Pointer>
196 struct __to_address_helper<_Pointer, decltype((void)pointer_traits<_Pointer>::to_address(declval<const _Pointer&>()))> {
197     _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
198     static decltype(pointer_traits<_Pointer>::to_address(declval<const _Pointer&>()))
199     __call(const _Pointer&__p) _NOEXCEPT {
200         return pointer_traits<_Pointer>::to_address(__p);
201     }
202 };
203 
204 #if _LIBCPP_STD_VER > 17
205 template <class _Pointer>
206 inline _LIBCPP_INLINE_VISIBILITY constexpr
207 auto to_address(const _Pointer& __p) noexcept {
208     return _VSTD::__to_address(__p);
209 }
210 #endif
211 
212 _LIBCPP_END_NAMESPACE_STD
213 
214 _LIBCPP_POP_MACROS
215 
216 #endif // _LIBCPP___MEMORY_POINTER_TRAITS_H
217