2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___MEMORY_POINTER_TRAITS_H
11 #define _LIBCPP___MEMORY_POINTER_TRAITS_H
14 #include <__memory/addressof.h>
15 #include <__type_traits/conditional.h>
16 #include <__type_traits/conjunction.h>
17 #include <__type_traits/decay.h>
18 #include <__type_traits/is_class.h>
19 #include <__type_traits/is_function.h>
20 #include <__type_traits/is_void.h>
21 #include <__type_traits/void_t.h>
22 #include <__utility/declval.h>
25 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
26 # pragma GCC system_header
29 _LIBCPP_BEGIN_NAMESPACE_STD
31 template <class _Tp
, class = void>
32 struct __has_element_type
: false_type
{};
35 struct __has_element_type
<_Tp
, __void_t
<typename
_Tp::element_type
> > : true_type
{};
37 template <class _Ptr
, bool = __has_element_type
<_Ptr
>::value
>
38 struct __pointer_traits_element_type
{};
41 struct __pointer_traits_element_type
<_Ptr
, true>
43 typedef _LIBCPP_NODEBUG typename
_Ptr::element_type type
;
46 template <template <class, class...> class _Sp
, class _Tp
, class ..._Args
>
47 struct __pointer_traits_element_type
<_Sp
<_Tp
, _Args
...>, true>
49 typedef _LIBCPP_NODEBUG typename _Sp
<_Tp
, _Args
...>::element_type type
;
52 template <template <class, class...> class _Sp
, class _Tp
, class ..._Args
>
53 struct __pointer_traits_element_type
<_Sp
<_Tp
, _Args
...>, false>
55 typedef _LIBCPP_NODEBUG _Tp type
;
58 template <class _Tp
, class = void>
59 struct __has_difference_type
: false_type
{};
62 struct __has_difference_type
<_Tp
, __void_t
<typename
_Tp::difference_type
> > : true_type
{};
64 template <class _Ptr
, bool = __has_difference_type
<_Ptr
>::value
>
65 struct __pointer_traits_difference_type
67 typedef _LIBCPP_NODEBUG
ptrdiff_t type
;
71 struct __pointer_traits_difference_type
<_Ptr
, true>
73 typedef _LIBCPP_NODEBUG typename
_Ptr::difference_type type
;
76 template <class _Tp
, class _Up
>
80 template <class _Xp
> static false_type
__test(...);
81 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
82 template <class _Xp
> static true_type
__test(typename
_Xp::template rebind
<_Up
>* = 0);
83 _LIBCPP_SUPPRESS_DEPRECATED_POP
85 static const bool value
= decltype(__test
<_Tp
>(0))::value
;
88 template <class _Tp
, class _Up
, bool = __has_rebind
<_Tp
, _Up
>::value
>
89 struct __pointer_traits_rebind
91 #ifndef _LIBCPP_CXX03_LANG
92 typedef _LIBCPP_NODEBUG typename
_Tp::template rebind
<_Up
> type
;
94 typedef _LIBCPP_NODEBUG typename
_Tp::template rebind
<_Up
>::other type
;
98 template <template <class, class...> class _Sp
, class _Tp
, class ..._Args
, class _Up
>
99 struct __pointer_traits_rebind
<_Sp
<_Tp
, _Args
...>, _Up
, true>
101 #ifndef _LIBCPP_CXX03_LANG
102 typedef _LIBCPP_NODEBUG typename _Sp
<_Tp
, _Args
...>::template rebind
<_Up
> type
;
104 typedef _LIBCPP_NODEBUG typename _Sp
<_Tp
, _Args
...>::template rebind
<_Up
>::other type
;
108 template <template <class, class...> class _Sp
, class _Tp
, class ..._Args
, class _Up
>
109 struct __pointer_traits_rebind
<_Sp
<_Tp
, _Args
...>, _Up
, false>
111 typedef _Sp
<_Up
, _Args
...> type
;
114 template <class _Ptr
, class = void>
115 struct __pointer_traits_impl
{};
117 template <class _Ptr
>
118 struct __pointer_traits_impl
<_Ptr
, __void_t
<typename __pointer_traits_element_type
<_Ptr
>::type
> > {
119 typedef _Ptr pointer
;
120 typedef typename __pointer_traits_element_type
<pointer
>::type element_type
;
121 typedef typename __pointer_traits_difference_type
<pointer
>::type difference_type
;
123 #ifndef _LIBCPP_CXX03_LANG
124 template <class _Up
> using rebind
= typename __pointer_traits_rebind
<pointer
, _Up
>::type
;
126 template <class _Up
> struct rebind
127 {typedef typename __pointer_traits_rebind
<pointer
, _Up
>::type other
;};
128 #endif // _LIBCPP_CXX03_LANG
133 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
134 static pointer
pointer_to(__conditional_t
<is_void
<element_type
>::value
, __nat
, element_type
>& __r
)
135 {return pointer::pointer_to(__r
);}
138 template <class _Ptr
>
139 struct _LIBCPP_TEMPLATE_VIS pointer_traits
: __pointer_traits_impl
<_Ptr
> {};
142 struct _LIBCPP_TEMPLATE_VIS pointer_traits
<_Tp
*>
144 typedef _Tp
* pointer
;
145 typedef _Tp element_type
;
146 typedef ptrdiff_t difference_type
;
148 #ifndef _LIBCPP_CXX03_LANG
149 template <class _Up
> using rebind
= _Up
*;
151 template <class _Up
> struct rebind
{typedef _Up
* other
;};
157 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
158 static pointer
pointer_to(__conditional_t
<is_void
<element_type
>::value
, __nat
, element_type
>& __r
) _NOEXCEPT
159 {return _VSTD::addressof(__r
);}
162 #ifndef _LIBCPP_CXX03_LANG
163 template <class _From
, class _To
>
164 using __rebind_pointer_t
= typename pointer_traits
<_From
>::template rebind
<_To
>;
166 template <class _From
, class _To
>
167 using __rebind_pointer_t
= typename pointer_traits
<_From
>::template rebind
<_To
>::other
;
172 template <class _Pointer
, class = void>
173 struct __to_address_helper
;
176 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
177 _Tp
* __to_address(_Tp
* __p
) _NOEXCEPT
{
178 static_assert(!is_function
<_Tp
>::value
, "_Tp is a function type");
182 template <class _Pointer
, class = void>
183 struct _HasToAddress
: false_type
{};
185 template <class _Pointer
>
186 struct _HasToAddress
<_Pointer
,
187 decltype((void)pointer_traits
<_Pointer
>::to_address(std::declval
<const _Pointer
&>()))
190 template <class _Pointer
, class = void>
191 struct _HasArrow
: false_type
{};
193 template <class _Pointer
>
194 struct _HasArrow
<_Pointer
,
195 decltype((void)std::declval
<const _Pointer
&>().operator->())
198 template <class _Pointer
>
199 struct _IsFancyPointer
{
200 static const bool value
= _HasArrow
<_Pointer
>::value
|| _HasToAddress
<_Pointer
>::value
;
203 // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers
204 template <class _Pointer
, class = __enable_if_t
<
205 _And
<is_class
<_Pointer
>, _IsFancyPointer
<_Pointer
> >::value
207 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
208 __decay_t
<decltype(__to_address_helper
<_Pointer
>::__call(std::declval
<const _Pointer
&>()))>
209 __to_address(const _Pointer
& __p
) _NOEXCEPT
{
210 return __to_address_helper
<_Pointer
>::__call(__p
);
213 template <class _Pointer
, class>
214 struct __to_address_helper
{
215 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
216 static decltype(_VSTD::__to_address(std::declval
<const _Pointer
&>().operator->()))
217 __call(const _Pointer
& __p
) _NOEXCEPT
{
218 return _VSTD::__to_address(__p
.operator->());
222 template <class _Pointer
>
223 struct __to_address_helper
<_Pointer
, decltype((void)pointer_traits
<_Pointer
>::to_address(std::declval
<const _Pointer
&>()))> {
224 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
225 static decltype(pointer_traits
<_Pointer
>::to_address(std::declval
<const _Pointer
&>()))
226 __call(const _Pointer
& __p
) _NOEXCEPT
{
227 return pointer_traits
<_Pointer
>::to_address(__p
);
231 #if _LIBCPP_STD_VER >= 20
233 inline _LIBCPP_INLINE_VISIBILITY
constexpr
234 auto to_address(_Tp
*__p
) noexcept
{
235 return _VSTD::__to_address(__p
);
238 template <class _Pointer
>
239 inline _LIBCPP_INLINE_VISIBILITY
constexpr
240 auto to_address(const _Pointer
& __p
) noexcept
-> decltype(std::__to_address(__p
)) {
241 return _VSTD::__to_address(__p
);
245 _LIBCPP_END_NAMESPACE_STD
247 #endif // _LIBCPP___MEMORY_POINTER_TRAITS_H