1 | /* |
2 | Copyright 2017-2018 Glen Joseph Fernandes |
3 | (glenjofe@gmail.com) |
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* |
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* |
195 | ptr_address(T* v, int) BOOST_NOEXCEPT |
196 | { |
197 | return v; |
198 | } |
199 | |
200 | template<class T> |
201 | inline auto |
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 |
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 |
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* |
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 | |