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