1 /*
2 Copyright 2017-2018 Glen Joseph Fernandes
3 ([email protected])
4
5 Distributed 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 #if !defined(BOOST_NO_CXX11_POINTER_TRAITS)
13 #include <memory>
14 #else
15 #include <boost/core/addressof.hpp>
16 #include <cstddef>
17 #endif
18
19 namespace boost {
20
21 #if !defined(BOOST_NO_CXX11_POINTER_TRAITS)
22 template<class T>
23 struct pointer_traits
24 : std::pointer_traits<T> {
25 template<class U>
26 struct rebind_to {
27 typedef typename std::pointer_traits<T>::template rebind<U> type;
28 };
29 };
30
31 template<class T>
32 struct pointer_traits<T*>
33 : std::pointer_traits<T*> {
34 template<class U>
35 struct rebind_to {
36 typedef U* type;
37 };
38 };
39 #else
40 namespace detail {
41
42 template<class>
43 struct ptr_void {
44 typedef void type;
45 };
46
47 template<class T>
48 struct ptr_first;
49
50 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
51 template<template<class, class...> class T, class U, class... Args>
52 struct ptr_first<T<U, Args...> > {
53 typedef U type;
54 };
55 #else
56 template<template<class> class T, class U>
57 struct ptr_first<T<U> > {
58 typedef U type;
59 };
60
61 template<template<class, class> class T, class U1, class U2>
62 struct ptr_first<T<U1, U2> > {
63 typedef U1 type;
64 };
65
66 template<template<class, class, class> class T, class U1, class U2, class U3>
67 struct ptr_first<T<U1, U2, U3> > {
68 typedef U1 type;
69 };
70 #endif
71
72 template<class T, class = void>
73 struct ptr_element {
74 typedef typename ptr_first<T>::type type;
75 };
76
77 template<class T>
78 struct ptr_element<T, typename ptr_void<typename T::element_type>::type> {
79 typedef typename T::element_type type;
80 };
81
82 template<class, class = void>
83 struct ptr_difference {
84 typedef std::ptrdiff_t type;
85 };
86
87 template<class T>
88 struct ptr_difference<T,
89 typename ptr_void<typename T::difference_type>::type> {
90 typedef typename T::difference_type type;
91 };
92
93 template<class T, class V>
94 struct ptr_transform;
95
96 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
97 template<template<class, class...> class T, class U, class... Args, class V>
98 struct ptr_transform<T<U, Args...>, V> {
99 typedef T<V, Args...> type;
100 };
101 #else
102 template<template<class> class T, class U, class V>
103 struct ptr_transform<T<U>, V> {
104 typedef T<V> type;
105 };
106
107 template<template<class, class> class T, class U1, class U2, class V>
108 struct ptr_transform<T<U1, U2>, V> {
109 typedef T<V, U2> type;
110 };
111
112 template<template<class, class, class> class T,
113 class U1, class U2, class U3, class V>
114 struct ptr_transform<T<U1, U2, U3>, V> {
115 typedef T<V, U2, U3> type;
116 };
117 #endif
118
119 template<class T, class U, class = void>
120 struct ptr_rebind {
121 typedef typename ptr_transform<T, U>::type type;
122 };
123
124 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
125 template<class T, class U>
126 struct ptr_rebind<T, U,
127 typename ptr_void<typename T::template rebind<U> >::type> {
128 typedef typename T::template rebind<U> type;
129 };
130 #endif
131
132 template<class T>
133 struct ptr_value {
134 typedef T type;
135 };
136
137 template<>
138 struct ptr_value<void> {
139 typedef struct { } type;
140 };
141
142 } /* detail */
143
144 template<class T>
145 struct pointer_traits {
146 typedef T pointer;
147 typedef typename detail::ptr_element<T>::type element_type;
148 typedef typename detail::ptr_difference<T>::type difference_type;
149 template<class U>
150 struct rebind_to {
151 typedef typename detail::ptr_rebind<T, U>::type type;
152 };
153 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
154 template<class U>
155 using rebind = typename detail::ptr_rebind<T, U>::type;
156 #endif
157 static pointer
158 pointer_to(typename detail::ptr_value<element_type>::type& v) {
159 return pointer::pointer_to(v);
160 }
161 };
162
163 template<class T>
164 struct pointer_traits<T*> {
165 typedef T* pointer;
166 typedef T element_type;
167 typedef std::ptrdiff_t difference_type;
168 template<class U>
169 struct rebind_to {
170 typedef U* type;
171 };
172 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
173 template<class U>
174 using rebind = U*;
175 #endif
176 static T*
177 pointer_to(typename detail::ptr_value<T>::type& v) BOOST_NOEXCEPT {
178 return boost::addressof(v);
179 }
180 };
181 #endif
182
183 template<class T>
184 BOOST_CONSTEXPR inline T*
to_address(T * v)185 to_address(T* v) BOOST_NOEXCEPT
186 {
187 return v;
188 }
189
190 #if !defined(BOOST_NO_CXX14_RETURN_TYPE_DEDUCTION)
191 namespace detail {
192
193 template<class T>
194 inline T*
ptr_address(T * v,int)195 ptr_address(T* v, int) BOOST_NOEXCEPT
196 {
197 return v;
198 }
199
200 template<class T>
201 inline auto
ptr_address(const T & v,int)202 ptr_address(const T& v, int) BOOST_NOEXCEPT
203 -> decltype(boost::pointer_traits<T>::to_address(v))
204 {
205 return boost::pointer_traits<T>::to_address(v);
206 }
207
208 template<class T>
209 inline auto
ptr_address(const T & v,long)210 ptr_address(const T& v, long) BOOST_NOEXCEPT
211 {
212 return boost::detail::ptr_address(v.operator->(), 0);
213 }
214
215 } /* detail */
216
217 template<class T>
218 inline auto
to_address(const T & v)219 to_address(const T& v) BOOST_NOEXCEPT
220 {
221 return boost::detail::ptr_address(v, 0);
222 }
223 #else
224 template<class T>
225 inline typename pointer_traits<T>::element_type*
to_address(const T & v)226 to_address(const T& v) BOOST_NOEXCEPT
227 {
228 return boost::to_address(v.operator->());
229 }
230 #endif
231
232 } /* boost */
233
234 #endif
235