1 | /* |
2 | Copyright (C) 2002 Brad King (brad.king@kitware.com) |
3 | Douglas Gregor (gregod@cs.rpi.edu) |
4 | |
5 | Copyright (C) 2002, 2008, 2013 Peter Dimov |
6 | |
7 | Copyright (C) 2017 Glen Joseph Fernandes (glenjofe@gmail.com) |
8 | |
9 | Distributed under the Boost Software License, Version 1.0. |
10 | (See accompanying file LICENSE_1_0.txt or copy at |
11 | http://www.boost.org/LICENSE_1_0.txt) |
12 | */ |
13 | |
14 | #ifndef BOOST_CORE_ADDRESSOF_HPP |
15 | #define BOOST_CORE_ADDRESSOF_HPP |
16 | |
17 | #include <boost/config.hpp> |
18 | |
19 | #if defined(BOOST_MSVC_FULL_VER) && BOOST_MSVC_FULL_VER >= 190024215 |
20 | #define BOOST_CORE_HAS_BUILTIN_ADDRESSOF |
21 | #elif defined(BOOST_GCC) && BOOST_GCC >= 70000 |
22 | #define BOOST_CORE_HAS_BUILTIN_ADDRESSOF |
23 | #elif defined(__has_builtin) |
24 | #if __has_builtin(__builtin_addressof) |
25 | #define BOOST_CORE_HAS_BUILTIN_ADDRESSOF |
26 | #endif |
27 | #endif |
28 | |
29 | #if defined(BOOST_CORE_HAS_BUILTIN_ADDRESSOF) |
30 | #if defined(BOOST_NO_CXX11_CONSTEXPR) |
31 | #define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF |
32 | #endif |
33 | |
34 | namespace boost { |
35 | |
36 | template<class T> |
37 | BOOST_CONSTEXPR inline T* |
38 | addressof(T& o) BOOST_NOEXCEPT |
39 | { |
40 | return __builtin_addressof(o); |
41 | } |
42 | |
43 | } /* boost */ |
44 | #else |
45 | #include <boost/config/workaround.hpp> |
46 | #include <cstddef> |
47 | |
48 | namespace boost { |
49 | namespace detail { |
50 | |
51 | template<class T> |
52 | class addressof_ref { |
53 | public: |
54 | BOOST_FORCEINLINE addressof_ref(T& o) BOOST_NOEXCEPT |
55 | : o_(o) { } |
56 | BOOST_FORCEINLINE operator T&() const BOOST_NOEXCEPT { |
57 | return o_; |
58 | } |
59 | private: |
60 | addressof_ref& operator=(const addressof_ref&); |
61 | T& o_; |
62 | }; |
63 | |
64 | template<class T> |
65 | struct address_of { |
66 | static BOOST_FORCEINLINE T* get(T& o, long) BOOST_NOEXCEPT { |
67 | return reinterpret_cast<T*>(& |
68 | const_cast<char&>(reinterpret_cast<const volatile char&>(o))); |
69 | } |
70 | static BOOST_FORCEINLINE T* get(T* p, int) BOOST_NOEXCEPT { |
71 | return p; |
72 | } |
73 | }; |
74 | |
75 | #if !defined(BOOST_NO_CXX11_NULLPTR) |
76 | #if !defined(BOOST_NO_CXX11_DECLTYPE) && \ |
77 | (defined(__INTEL_COMPILER) || \ |
78 | (defined(__clang__) && !defined(_LIBCPP_VERSION))) |
79 | typedef decltype(nullptr) addressof_null_t; |
80 | #else |
81 | typedef std::nullptr_t addressof_null_t; |
82 | #endif |
83 | |
84 | template<> |
85 | struct address_of<addressof_null_t> { |
86 | typedef addressof_null_t type; |
87 | static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { |
88 | return &o; |
89 | } |
90 | }; |
91 | |
92 | template<> |
93 | struct address_of<const addressof_null_t> { |
94 | typedef const addressof_null_t type; |
95 | static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { |
96 | return &o; |
97 | } |
98 | }; |
99 | |
100 | template<> |
101 | struct address_of<volatile addressof_null_t> { |
102 | typedef volatile addressof_null_t type; |
103 | static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { |
104 | return &o; |
105 | } |
106 | }; |
107 | |
108 | template<> |
109 | struct address_of<const volatile addressof_null_t> { |
110 | typedef const volatile addressof_null_t type; |
111 | static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT { |
112 | return &o; |
113 | } |
114 | }; |
115 | #endif |
116 | |
117 | } /* detail */ |
118 | |
119 | #if defined(BOOST_NO_CXX11_SFINAE_EXPR) || \ |
120 | defined(BOOST_NO_CXX11_CONSTEXPR) || \ |
121 | defined(BOOST_NO_CXX11_DECLTYPE) |
122 | #define BOOST_CORE_NO_CONSTEXPR_ADDRESSOF |
123 | |
124 | template<class T> |
125 | BOOST_FORCEINLINE T* |
126 | addressof(T& o) BOOST_NOEXCEPT |
127 | { |
128 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) || \ |
129 | BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120) |
130 | return detail::address_of<T>::get(o, 0); |
131 | #else |
132 | return detail::address_of<T>::get(detail::addressof_ref<T>(o), 0); |
133 | #endif |
134 | } |
135 | |
136 | #if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) |
137 | namespace detail { |
138 | |
139 | template<class T> |
140 | struct addressof_result { |
141 | typedef T* type; |
142 | }; |
143 | |
144 | } /* detail */ |
145 | |
146 | template<class T, std::size_t N> |
147 | BOOST_FORCEINLINE typename detail::addressof_result<T[N]>::type |
148 | addressof(T (&o)[N]) BOOST_NOEXCEPT |
149 | { |
150 | return &o; |
151 | } |
152 | #endif |
153 | |
154 | #if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564)) |
155 | template<class T, std::size_t N> |
156 | BOOST_FORCEINLINE |
157 | T (*addressof(T (&o)[N]) BOOST_NOEXCEPT)[N] |
158 | { |
159 | return reinterpret_cast<T(*)[N]>(&o); |
160 | } |
161 | |
162 | template<class T, std::size_t N> |
163 | BOOST_FORCEINLINE |
164 | const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N] |
165 | { |
166 | return reinterpret_cast<const T(*)[N]>(&o); |
167 | } |
168 | #endif |
169 | #else |
170 | namespace detail { |
171 | |
172 | template<class T> |
173 | T addressof_declval() BOOST_NOEXCEPT; |
174 | |
175 | template<class> |
176 | struct addressof_void { |
177 | typedef void type; |
178 | }; |
179 | |
180 | template<class T, class E = void> |
181 | struct addressof_member_operator { |
182 | static constexpr bool value = false; |
183 | }; |
184 | |
185 | template<class T> |
186 | struct addressof_member_operator<T, typename |
187 | addressof_void<decltype(addressof_declval<T&>().operator&())>::type> { |
188 | static constexpr bool value = true; |
189 | }; |
190 | |
191 | #if BOOST_WORKAROUND(BOOST_INTEL, < 1600) |
192 | struct addressof_addressable { }; |
193 | |
194 | addressof_addressable* |
195 | operator&(addressof_addressable&) BOOST_NOEXCEPT; |
196 | #endif |
197 | |
198 | template<class T, class E = void> |
199 | struct addressof_non_member_operator { |
200 | static constexpr bool value = false; |
201 | }; |
202 | |
203 | template<class T> |
204 | struct addressof_non_member_operator<T, typename |
205 | addressof_void<decltype(operator&(addressof_declval<T&>()))>::type> { |
206 | static constexpr bool value = true; |
207 | }; |
208 | |
209 | template<class T, class E = void> |
210 | struct addressof_expression { |
211 | static constexpr bool value = false; |
212 | }; |
213 | |
214 | template<class T> |
215 | struct addressof_expression<T, |
216 | typename addressof_void<decltype(&addressof_declval<T&>())>::type> { |
217 | static constexpr bool value = true; |
218 | }; |
219 | |
220 | template<class T> |
221 | struct addressof_is_constexpr { |
222 | static constexpr bool value = addressof_expression<T>::value && |
223 | !addressof_member_operator<T>::value && |
224 | !addressof_non_member_operator<T>::value; |
225 | }; |
226 | |
227 | template<bool E, class T> |
228 | struct addressof_if { }; |
229 | |
230 | template<class T> |
231 | struct addressof_if<true, T> { |
232 | typedef T* type; |
233 | }; |
234 | |
235 | template<class T> |
236 | BOOST_FORCEINLINE |
237 | typename addressof_if<!addressof_is_constexpr<T>::value, T>::type |
238 | addressof(T& o) BOOST_NOEXCEPT |
239 | { |
240 | return address_of<T>::get(addressof_ref<T>(o), 0); |
241 | } |
242 | |
243 | template<class T> |
244 | constexpr BOOST_FORCEINLINE |
245 | typename addressof_if<addressof_is_constexpr<T>::value, T>::type |
246 | addressof(T& o) BOOST_NOEXCEPT |
247 | { |
248 | return &o; |
249 | } |
250 | |
251 | } /* detail */ |
252 | |
253 | template<class T> |
254 | constexpr BOOST_FORCEINLINE T* |
255 | addressof(T& o) BOOST_NOEXCEPT |
256 | { |
257 | return detail::addressof(o); |
258 | } |
259 | #endif |
260 | |
261 | } /* boost */ |
262 | #endif |
263 | |
264 | #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES) && \ |
265 | !defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) |
266 | namespace boost { |
267 | |
268 | template<class T> |
269 | const T* addressof(const T&&) = delete; |
270 | |
271 | } /* boost */ |
272 | #endif |
273 | |
274 | #endif |
275 | |