1/*
2Copyright (C) 2002 Brad King (brad.king@kitware.com)
3 Douglas Gregor (gregod@cs.rpi.edu)
4
5Copyright (C) 2002, 2008, 2013 Peter Dimov
6
7Copyright (C) 2017 Glen Joseph Fernandes (glenjofe@gmail.com)
8
9Distributed under the Boost Software License, Version 1.0.
10(See accompanying file LICENSE_1_0.txt or copy at
11http://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
34namespace boost {
35
36template<class T>
37BOOST_CONSTEXPR inline T*
38addressof(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
48namespace boost {
49namespace detail {
50
51template<class T>
52class addrof_ref {
53public:
54 BOOST_FORCEINLINE addrof_ref(T& o) BOOST_NOEXCEPT
55 : o_(o) { }
56 BOOST_FORCEINLINE operator T&() const BOOST_NOEXCEPT {
57 return o_;
58 }
59private:
60 addrof_ref& operator=(const addrof_ref&);
61 T& o_;
62};
63
64template<class T>
65struct addrof {
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)))
79typedef decltype(nullptr) addrof_null_t;
80#else
81typedef std::nullptr_t addrof_null_t;
82#endif
83
84template<>
85struct addrof<addrof_null_t> {
86 typedef addrof_null_t type;
87 static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
88 return &o;
89 }
90};
91
92template<>
93struct addrof<const addrof_null_t> {
94 typedef const addrof_null_t type;
95 static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
96 return &o;
97 }
98};
99
100template<>
101struct addrof<volatile addrof_null_t> {
102 typedef volatile addrof_null_t type;
103 static BOOST_FORCEINLINE type* get(type& o, int) BOOST_NOEXCEPT {
104 return &o;
105 }
106};
107
108template<>
109struct addrof<const volatile addrof_null_t> {
110 typedef const volatile addrof_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
124template<class T>
125BOOST_FORCEINLINE T*
126addressof(T& o) BOOST_NOEXCEPT
127{
128#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x610)) || \
129 BOOST_WORKAROUND(__SUNPRO_CC, <= 0x5120)
130 return boost::detail::addrof<T>::get(o, 0);
131#else
132 return boost::detail::addrof<T>::get(boost::detail::addrof_ref<T>(o), 0);
133#endif
134}
135
136#if BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))
137namespace detail {
138
139template<class T>
140struct addrof_result {
141 typedef T* type;
142};
143
144} /* detail */
145
146template<class T, std::size_t N>
147BOOST_FORCEINLINE typename boost::detail::addrof_result<T[N]>::type
148addressof(T (&o)[N]) BOOST_NOEXCEPT
149{
150 return &o;
151}
152#endif
153
154#if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x564))
155template<class T, std::size_t N>
156BOOST_FORCEINLINE
157T (*addressof(T (&o)[N]) BOOST_NOEXCEPT)[N]
158{
159 return reinterpret_cast<T(*)[N]>(&o);
160}
161
162template<class T, std::size_t N>
163BOOST_FORCEINLINE
164const T (*addressof(const T (&o)[N]) BOOST_NOEXCEPT)[N]
165{
166 return reinterpret_cast<const T(*)[N]>(&o);
167}
168#endif
169#else
170namespace detail {
171
172template<class T>
173T addrof_declval() BOOST_NOEXCEPT;
174
175template<class>
176struct addrof_void {
177 typedef void type;
178};
179
180template<class T, class E = void>
181struct addrof_member_operator {
182 static constexpr bool value = false;
183};
184
185template<class T>
186struct addrof_member_operator<T, typename
187 addrof_void<decltype(addrof_declval<T&>().operator&())>::type> {
188 static constexpr bool value = true;
189};
190
191#if BOOST_WORKAROUND(BOOST_INTEL, < 1600)
192struct addrof_addressable { };
193
194addrof_addressable*
195operator&(addrof_addressable&) BOOST_NOEXCEPT;
196#endif
197
198template<class T, class E = void>
199struct addrof_non_member_operator {
200 static constexpr bool value = false;
201};
202
203template<class T>
204struct addrof_non_member_operator<T, typename
205 addrof_void<decltype(operator&(addrof_declval<T&>()))>::type> {
206 static constexpr bool value = true;
207};
208
209template<class T, class E = void>
210struct addrof_expression {
211 static constexpr bool value = false;
212};
213
214template<class T>
215struct addrof_expression<T,
216 typename addrof_void<decltype(&addrof_declval<T&>())>::type> {
217 static constexpr bool value = true;
218};
219
220template<class T>
221struct addrof_is_constexpr {
222 static constexpr bool value = addrof_expression<T>::value &&
223 !addrof_member_operator<T>::value &&
224 !addrof_non_member_operator<T>::value;
225};
226
227template<bool E, class T>
228struct addrof_if { };
229
230template<class T>
231struct addrof_if<true, T> {
232 typedef T* type;
233};
234
235template<class T>
236BOOST_FORCEINLINE
237typename addrof_if<!addrof_is_constexpr<T>::value, T>::type
238addressof(T& o) BOOST_NOEXCEPT
239{
240 return addrof<T>::get(addrof_ref<T>(o), 0);
241}
242
243template<class T>
244constexpr BOOST_FORCEINLINE
245typename addrof_if<addrof_is_constexpr<T>::value, T>::type
246addressof(T& o) BOOST_NOEXCEPT
247{
248 return &o;
249}
250
251} /* detail */
252
253template<class T>
254constexpr BOOST_FORCEINLINE T*
255addressof(T& o) BOOST_NOEXCEPT
256{
257 return boost::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)
266namespace boost {
267
268template<class T>
269const T* addressof(const T&&) = delete;
270
271} /* boost */
272#endif
273
274#endif
275