1 /*
2 Copyright 2017 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 #endif
17 
18 namespace boost {
19 
20 template<class T>
21 struct pointer_traits;
22 
23 namespace detail {
24 
25 template<class U>
26 inline typename boost::pointer_traits<U>::element_type*
ptr_traits_address(const U & v)27 ptr_traits_address(const U& v) BOOST_NOEXCEPT
28 {
29     return boost::pointer_traits<U>::to_address(v);
30 }
31 
32 } /* detail */
33 
34 #if !defined(BOOST_NO_CXX11_POINTER_TRAITS)
35 template<class T>
36 struct pointer_traits
37     : std::pointer_traits<T> {
38     template<class U>
39     struct rebind_to {
40         typedef typename std::pointer_traits<T>::template rebind<U> type;
41     };
42     static typename std::pointer_traits<T>::element_type*
to_addressboost::pointer_traits43     to_address(const T& v) BOOST_NOEXCEPT {
44         return detail::ptr_traits_address(v.operator->());
45     }
46 };
47 
48 template<class T>
49 struct pointer_traits<T*>
50     : std::pointer_traits<T*> {
51     template<class U>
52     struct rebind_to {
53         typedef U* type;
54     };
to_addressboost::pointer_traits55     static T* to_address(T* v) BOOST_NOEXCEPT {
56         return v;
57     }
58 };
59 #else
60 namespace detail {
61 
62 struct ptr_traits_none { char first, second; };
63 
64 template<class T>
65 struct ptr_traits_has_element {
66 private:
67     template<class U>
68     static ptr_traits_none call(...);
69     template<class U>
70     static char call(typename U::element_type* = 0);
71 public:
72     static const bool value = sizeof(call<T>(0)) == 1;
73 };
74 
75 template<class T>
76 struct ptr_traits_first;
77 
78 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
79 template<template<class, class...> class T, class U, class... Args>
80 struct ptr_traits_first<T<U, Args...> > {
81     typedef U type;
82 };
83 #else
84 template<template<class> class T, class U>
85 struct ptr_traits_first<T<U> > {
86     typedef U type;
87 };
88 
89 template<template<class, class> class T, class U1, class U2>
90 struct ptr_traits_first<T<U1, U2> > {
91     typedef U1 type;
92 };
93 
94 template<template<class, class, class> class T, class U1, class U2, class U3>
95 struct ptr_traits_first<T<U1, U2, U3> > {
96     typedef U1 type;
97 };
98 #endif
99 
100 template<class T, bool = ptr_traits_has_element<T>::value>
101 struct ptr_traits_element {
102     typedef typename T::element_type type;
103 };
104 
105 template<class T>
106 struct ptr_traits_element<T, false> {
107     typedef typename ptr_traits_first<T>::type type;
108 };
109 
110 template<class T>
111 struct ptr_traits_has_difference {
112 private:
113     template<class U>
114     static ptr_traits_none call(...);
115     template<class U>
116     static char call(typename U::difference_type* = 0);
117 public:
118     static const bool value = sizeof(call<T>(0)) == 1;
119 };
120 
121 template<class T, bool = ptr_traits_has_difference<T>::value>
122 struct ptr_traits_difference {
123     typedef typename T::difference_type type;
124 };
125 
126 template<class T>
127 struct ptr_traits_difference<T, false> {
128     typedef std::ptrdiff_t type;
129 };
130 
131 template<class T, class V>
132 struct ptr_traits_has_rebind {
133 private:
134     template<class U>
135     static ptr_traits_none call(...);
136     template<class U>
137     static char call(typename U::template rebind<V>* = 0);
138 public:
139     static const bool value = sizeof(call<T>(0)) == 1;
140 };
141 
142 template<class T, class V>
143 struct ptr_traits_rebind_to;
144 
145 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
146 template<template<class, class...> class T, class U, class... Args, class V>
147 struct ptr_traits_rebind_to<T<U, Args...>, V> {
148     typedef T<V, Args...> type;
149 };
150 #else
151 template<template<class> class T, class U, class V>
152 struct ptr_traits_rebind_to<T<U>, V> {
153     typedef T<V> type;
154 };
155 
156 template<template<class, class> class T, class U1, class U2, class V>
157 struct ptr_traits_rebind_to<T<U1, U2>, V> {
158     typedef T<V, U2> type;
159 };
160 
161 template<template<class, class, class> class T,
162     class U1, class U2, class U3, class V>
163 struct ptr_traits_rebind_to<T<U1, U2, U3>, V> {
164     typedef T<V, U2, U3> type;
165 };
166 #endif
167 
168 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
169 template<class T, class U, bool = ptr_traits_has_rebind<T, U>::value>
170 struct ptr_traits_rebind {
171     typedef typename T::template rebind<U> type;
172 };
173 
174 template<class T, class U>
175 struct ptr_traits_rebind<T, U, false> {
176     typedef typename ptr_traits_rebind_to<T, U>::type type;
177 };
178 #else
179 template<class T, class U>
180 struct ptr_traits_rebind {
181     typedef typename ptr_traits_rebind_to<T, U>::type type;
182 };
183 #endif
184 
185 template<class T>
186 struct ptr_traits_value {
187     typedef T type;
188 };
189 
190 template<>
191 struct ptr_traits_value<void> {
192     typedef struct { } type;
193 };
194 
195 } /* detail */
196 
197 template<class T>
198 struct pointer_traits {
199     typedef T pointer;
200     typedef typename detail::ptr_traits_element<T>::type element_type;
201     typedef typename detail::ptr_traits_difference<T>::type difference_type;
202     template<class U>
203     struct rebind_to {
204         typedef typename detail::ptr_traits_rebind<T, U>::type type;
205     };
206 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
207     template<class U>
208     using rebind = typename detail::ptr_traits_rebind<T, U>::type;
209 #endif
210     static pointer
pointer_toboost::pointer_traits211     pointer_to(typename detail::ptr_traits_value<element_type>::type& v) {
212         return pointer::pointer_to(v);
213     }
to_addressboost::pointer_traits214     static element_type* to_address(const pointer& v) BOOST_NOEXCEPT {
215         return detail::ptr_traits_address(v.operator->());
216     }
217 };
218 
219 template<class T>
220 struct pointer_traits<T*> {
221     typedef T* pointer;
222     typedef T element_type;
223     typedef std::ptrdiff_t difference_type;
224     template<class U>
225     struct rebind_to {
226         typedef U* type;
227     };
228 #if !defined(BOOST_NO_CXX11_TEMPLATE_ALIASES)
229     template<class U>
230     using rebind = U*;
231 #endif
232     static T*
pointer_toboost::pointer_traits233     pointer_to(typename detail::ptr_traits_value<T>::type& v) BOOST_NOEXCEPT {
234         return addressof(v);
235     }
to_addressboost::pointer_traits236     static T* to_address(T* v) BOOST_NOEXCEPT {
237         return v;
238     }
239 };
240 #endif
241 
242 template<class T>
243 inline typename pointer_traits<T>::element_type*
to_address(const T & v)244 to_address(const T& v) BOOST_NOEXCEPT
245 {
246     return pointer_traits<T>::to_address(v);
247 }
248 
249 template<class T>
250 inline T*
to_address(T * v)251 to_address(T* v) BOOST_NOEXCEPT
252 {
253     return v;
254 }
255 
256 } /* boost */
257 
258 #endif
259