1/*
2Copyright 2017-2021 Glen Joseph Fernandes
3(glenjofe@gmail.com)
4
5Distributed under the Boost Software License, Version 1.0.
6(http://www.boost.org/LICENSE_1_0.txt)
7*/
8#ifndef BOOST_CORE_POINTER_TRAITS_HPP
9#define BOOST_CORE_POINTER_TRAITS_HPP
10
11#include <boost/config.hpp>
12#include <boost/core/addressof.hpp>
13#include <cstddef>
14
15namespace boost {
16namespace detail {
17
18struct ptr_none { };
19
20template<class>
21struct ptr_valid {
22 typedef void type;
23};
24
25template<class>
26struct ptr_first {
27 typedef ptr_none type;
28};
29
30#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
31template<template<class, class...> class T, class U, class... Args>
32struct ptr_first<T<U, Args...> > {
33 typedef U type;
34};
35#else
36template<template<class> class T, class U>
37struct ptr_first<T<U> > {
38 typedef U type;
39};
40
41template<template<class, class> class T, class U1, class U2>
42struct ptr_first<T<U1, U2> > {
43 typedef U1 type;
44};
45
46template<template<class, class, class> class T, class U1, class U2, class U3>
47struct ptr_first<T<U1, U2, U3> > {
48 typedef U1 type;
49};
50#endif
51
52template<class T, class = void>
53struct ptr_element {
54 typedef typename ptr_first<T>::type type;
55};
56
57template<class T>
58struct ptr_element<T, typename ptr_valid<typename T::element_type>::type> {
59 typedef typename T::element_type type;
60};
61
62template<class, class = void>
63struct ptr_difference {
64 typedef std::ptrdiff_t type;
65};
66
67template<class T>
68struct ptr_difference<T,
69 typename ptr_valid<typename T::difference_type>::type> {
70 typedef typename T::difference_type type;
71};
72
73template<class, class>
74struct ptr_transform { };
75
76#if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
77template<template<class, class...> class T, class U, class... Args, class V>
78struct ptr_transform<T<U, Args...>, V> {
79 typedef T<V, Args...> type;
80};
81#else
82template<template<class> class T, class U, class V>
83struct ptr_transform<T<U>, V> {
84 typedef T<V> type;
85};
86
87template<template<class, class> class T, class U1, class U2, class V>
88struct ptr_transform<T<U1, U2>, V> {
89 typedef T<V, U2> type;
90};
91
92template<template<class, class, class> class T,
93 class U1, class U2, class U3, class V>
94struct ptr_transform<T<U1, U2, U3>, V> {
95 typedef T<V, U2, U3> type;
96};
97#endif
98
99template<class T, class U, class = void>
100struct ptr_rebind
101 : ptr_transform<T, U> { };
102
103#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
104template<class T, class U>
105struct ptr_rebind<T, U,
106 typename ptr_valid<typename T::template rebind<U> >::type> {
107 typedef typename T::template rebind<U> type;
108};
109#else
110template<class T, class U>
111struct ptr_rebind<T, U,
112 typename ptr_valid<typename T::template rebind<U>::other>::type> {
113 typedef typename T::template rebind<U>::other type;
114};
115#endif
116
117#if !defined(BOOST_NO_CXX11_DECLTYPE_N3276)
118template<class T, class E>
119class ptr_to_expr {
120 template<class>
121 struct result {
122 char x, y;
123 };
124
125 static E& source();
126
127 template<class O>
128 static auto check(int) -> result<decltype(O::pointer_to(source()))>;
129
130 template<class>
131 static char check(long);
132
133public:
134 BOOST_STATIC_CONSTEXPR bool value = sizeof(check<T>(0)) > 1;
135};
136
137template<class T, class E>
138struct ptr_to_expr<T*, E> {
139 BOOST_STATIC_CONSTEXPR bool value = true;
140};
141
142template<class T, class E>
143struct ptr_has_to {
144 BOOST_STATIC_CONSTEXPR bool value = ptr_to_expr<T, E>::value;
145};
146#else
147template<class, class>
148struct ptr_has_to {
149 BOOST_STATIC_CONSTEXPR bool value = true;
150};
151#endif
152
153template<class T>
154struct ptr_has_to<T, void> {
155 BOOST_STATIC_CONSTEXPR bool value = false;
156};
157
158template<class T>
159struct ptr_has_to<T, const void> {
160 BOOST_STATIC_CONSTEXPR bool value = false;
161};
162
163template<class T>
164struct ptr_has_to<T, volatile void> {
165 BOOST_STATIC_CONSTEXPR bool value = false;
166};
167
168template<class T>
169struct ptr_has_to<T, const volatile void> {
170 BOOST_STATIC_CONSTEXPR bool value = false;
171};
172
173template<class T, class E, bool = ptr_has_to<T, E>::value>
174struct ptr_to { };
175
176template<class T, class E>
177struct ptr_to<T, E, true> {
178 static T pointer_to(E& v) {
179 return T::pointer_to(v);
180 }
181};
182
183template<class T>
184struct ptr_to<T*, T, true> {
185 static T* pointer_to(T& v) BOOST_NOEXCEPT {
186 return boost::addressof(v);
187 }
188};
189
190template<class T, class E>
191struct ptr_traits
192 : ptr_to<T, E> {
193 typedef T pointer;
194 typedef E element_type;
195 typedef typename ptr_difference<T>::type difference_type;
196
197 template<class U>
198 struct rebind_to
199 : ptr_rebind<T, U> { };
200
201#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
202 template<class U>
203 using rebind = typename rebind_to<U>::type;
204#endif
205};
206
207template<class T>
208struct ptr_traits<T, ptr_none> { };
209
210} /* detail */
211
212template<class T>
213struct pointer_traits
214 : detail::ptr_traits<T, typename detail::ptr_element<T>::type> { };
215
216template<class T>
217struct pointer_traits<T*>
218 : detail::ptr_to<T*, T> {
219 typedef T* pointer;
220 typedef T element_type;
221 typedef std::ptrdiff_t difference_type;
222
223 template<class U>
224 struct rebind_to {
225 typedef U* type;
226 };
227
228#if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
229 template<class U>
230 using rebind = typename rebind_to<U>::type;
231#endif
232};
233
234template<class T>
235BOOST_CONSTEXPR inline T*
236to_address(T* v) BOOST_NOEXCEPT
237{
238 return v;
239}
240
241#if !defined(BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION)
242namespace detail {
243
244template<class T>
245inline T*
246ptr_address(T* v, int) BOOST_NOEXCEPT
247{
248 return v;
249}
250
251template<class T>
252inline auto
253ptr_address(const T& v, int) BOOST_NOEXCEPT
254-> decltype(boost::pointer_traits<T>::to_address(v))
255{
256 return boost::pointer_traits<T>::to_address(v);
257}
258
259template<class T>
260inline auto
261ptr_address(const T& v, long) BOOST_NOEXCEPT
262{
263 return boost::detail::ptr_address(v.operator->(), 0);
264}
265
266} /* detail */
267
268template<class T>
269inline auto
270to_address(const T& v) BOOST_NOEXCEPT
271{
272 return boost::detail::ptr_address(v, 0);
273}
274#else
275template<class T>
276inline typename pointer_traits<T>::element_type*
277to_address(const T& v) BOOST_NOEXCEPT
278{
279 return boost::to_address(v.operator->());
280}
281#endif
282
283} /* boost */
284
285#endif
286