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>
17 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
18 #pragma GCC system_header
21 _LIBCPP_BEGIN_NAMESPACE_STD
23 template <class _Tp
, class = void>
24 struct __has_element_type
: false_type
{};
27 struct __has_element_type
<_Tp
,
28 typename __void_t
<typename
_Tp::element_type
>::type
> : true_type
{};
30 template <class _Ptr
, bool = __has_element_type
<_Ptr
>::value
>
31 struct __pointer_traits_element_type
;
34 struct __pointer_traits_element_type
<_Ptr
, true>
36 typedef _LIBCPP_NODEBUG typename
_Ptr::element_type type
;
39 template <template <class, class...> class _Sp
, class _Tp
, class ..._Args
>
40 struct __pointer_traits_element_type
<_Sp
<_Tp
, _Args
...>, true>
42 typedef _LIBCPP_NODEBUG typename _Sp
<_Tp
, _Args
...>::element_type type
;
45 template <template <class, class...> class _Sp
, class _Tp
, class ..._Args
>
46 struct __pointer_traits_element_type
<_Sp
<_Tp
, _Args
...>, false>
48 typedef _LIBCPP_NODEBUG _Tp type
;
51 template <class _Tp
, class = void>
52 struct __has_difference_type
: false_type
{};
55 struct __has_difference_type
<_Tp
,
56 typename __void_t
<typename
_Tp::difference_type
>::type
> : true_type
{};
58 template <class _Ptr
, bool = __has_difference_type
<_Ptr
>::value
>
59 struct __pointer_traits_difference_type
61 typedef _LIBCPP_NODEBUG
ptrdiff_t type
;
65 struct __pointer_traits_difference_type
<_Ptr
, true>
67 typedef _LIBCPP_NODEBUG typename
_Ptr::difference_type type
;
70 template <class _Tp
, class _Up
>
74 struct __two
{char __lx
; char __lxx
;};
75 template <class _Xp
> static __two
__test(...);
76 _LIBCPP_SUPPRESS_DEPRECATED_PUSH
77 template <class _Xp
> static char __test(typename
_Xp::template rebind
<_Up
>* = 0);
78 _LIBCPP_SUPPRESS_DEPRECATED_POP
80 static const bool value
= sizeof(__test
<_Tp
>(0)) == 1;
83 template <class _Tp
, class _Up
, bool = __has_rebind
<_Tp
, _Up
>::value
>
84 struct __pointer_traits_rebind
86 #ifndef _LIBCPP_CXX03_LANG
87 typedef _LIBCPP_NODEBUG typename
_Tp::template rebind
<_Up
> type
;
89 typedef _LIBCPP_NODEBUG typename
_Tp::template rebind
<_Up
>::other type
;
93 template <template <class, class...> class _Sp
, class _Tp
, class ..._Args
, class _Up
>
94 struct __pointer_traits_rebind
<_Sp
<_Tp
, _Args
...>, _Up
, true>
96 #ifndef _LIBCPP_CXX03_LANG
97 typedef _LIBCPP_NODEBUG typename _Sp
<_Tp
, _Args
...>::template rebind
<_Up
> type
;
99 typedef _LIBCPP_NODEBUG typename _Sp
<_Tp
, _Args
...>::template rebind
<_Up
>::other type
;
103 template <template <class, class...> class _Sp
, class _Tp
, class ..._Args
, class _Up
>
104 struct __pointer_traits_rebind
<_Sp
<_Tp
, _Args
...>, _Up
, false>
106 typedef _Sp
<_Up
, _Args
...> type
;
109 template <class _Ptr
>
110 struct _LIBCPP_TEMPLATE_VIS pointer_traits
112 typedef _Ptr pointer
;
113 typedef typename __pointer_traits_element_type
<pointer
>::type element_type
;
114 typedef typename __pointer_traits_difference_type
<pointer
>::type difference_type
;
116 #ifndef _LIBCPP_CXX03_LANG
117 template <class _Up
> using rebind
= typename __pointer_traits_rebind
<pointer
, _Up
>::type
;
119 template <class _Up
> struct rebind
120 {typedef typename __pointer_traits_rebind
<pointer
, _Up
>::type other
;};
121 #endif // _LIBCPP_CXX03_LANG
126 _LIBCPP_INLINE_VISIBILITY
127 static pointer
pointer_to(typename conditional
<is_void
<element_type
>::value
,
128 __nat
, element_type
>::type
& __r
)
129 {return pointer::pointer_to(__r
);}
133 struct _LIBCPP_TEMPLATE_VIS pointer_traits
<_Tp
*>
135 typedef _Tp
* pointer
;
136 typedef _Tp element_type
;
137 typedef ptrdiff_t difference_type
;
139 #ifndef _LIBCPP_CXX03_LANG
140 template <class _Up
> using rebind
= _Up
*;
142 template <class _Up
> struct rebind
{typedef _Up
* other
;};
148 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX17
149 static pointer
pointer_to(typename conditional
<is_void
<element_type
>::value
,
150 __nat
, element_type
>::type
& __r
) _NOEXCEPT
151 {return _VSTD::addressof(__r
);}
154 template <class _From
, class _To
>
155 struct __rebind_pointer
{
156 #ifndef _LIBCPP_CXX03_LANG
157 typedef typename pointer_traits
<_From
>::template rebind
<_To
> type
;
159 typedef typename pointer_traits
<_From
>::template rebind
<_To
>::other type
;
165 template <class _Pointer
, class = void>
166 struct __to_address_helper
;
169 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
170 _Tp
* __to_address(_Tp
* __p
) _NOEXCEPT
{
171 static_assert(!is_function
<_Tp
>::value
, "_Tp is a function type");
175 // enable_if is needed here to avoid instantiating checks for fancy pointers on raw pointers
176 template <class _Pointer
, class = __enable_if_t
<
177 !is_pointer
<_Pointer
>::value
&& !is_array
<_Pointer
>::value
&& !is_function
<_Pointer
>::value
179 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
180 typename decay
<decltype(__to_address_helper
<_Pointer
>::__call(declval
<const _Pointer
&>()))>::type
181 __to_address(const _Pointer
& __p
) _NOEXCEPT
{
182 return __to_address_helper
<_Pointer
>::__call(__p
);
185 template <class _Pointer
, class>
186 struct __to_address_helper
{
187 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
188 static decltype(_VSTD::__to_address(declval
<const _Pointer
&>().operator->()))
189 __call(const _Pointer
& __p
) _NOEXCEPT
{
190 return _VSTD::__to_address(__p
.operator->());
194 template <class _Pointer
>
195 struct __to_address_helper
<_Pointer
, decltype((void)pointer_traits
<_Pointer
>::to_address(declval
<const _Pointer
&>()))> {
196 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
197 static decltype(pointer_traits
<_Pointer
>::to_address(declval
<const _Pointer
&>()))
198 __call(const _Pointer
& __p
) _NOEXCEPT
{
199 return pointer_traits
<_Pointer
>::to_address(__p
);
203 #if _LIBCPP_STD_VER > 17
205 inline _LIBCPP_INLINE_VISIBILITY
constexpr
206 auto to_address(_Tp
*__p
) noexcept
{
207 return _VSTD::__to_address(__p
);
210 template <class _Pointer
>
211 inline _LIBCPP_INLINE_VISIBILITY
constexpr
212 auto to_address(const _Pointer
& __p
) noexcept
{
213 return _VSTD::__to_address(__p
);
217 _LIBCPP_END_NAMESPACE_STD
219 #endif // _LIBCPP___MEMORY_POINTER_TRAITS_H