1 | // See http://www.boost.org/libs/any for Documentation. |
2 | |
3 | #ifndef BOOST_ANY_INCLUDED |
4 | #define BOOST_ANY_INCLUDED |
5 | |
6 | #if defined(_MSC_VER) |
7 | # pragma once |
8 | #endif |
9 | |
10 | // what: variant type boost::any |
11 | // who: contributed by Kevlin Henney, |
12 | // with features contributed and bugs found by |
13 | // Antony Polukhin, Ed Brey, Mark Rodgers, |
14 | // Peter Dimov, and James Curran |
15 | // when: July 2001, April 2013 - 2020 |
16 | |
17 | #include <boost/config.hpp> |
18 | #include <boost/type_index.hpp> |
19 | #include <boost/type_traits/remove_reference.hpp> |
20 | #include <boost/type_traits/decay.hpp> |
21 | #include <boost/type_traits/remove_cv.hpp> |
22 | #include <boost/type_traits/add_reference.hpp> |
23 | #include <boost/type_traits/is_reference.hpp> |
24 | #include <boost/type_traits/is_const.hpp> |
25 | #include <boost/throw_exception.hpp> |
26 | #include <boost/static_assert.hpp> |
27 | #include <boost/utility/enable_if.hpp> |
28 | #include <boost/core/addressof.hpp> |
29 | #include <boost/type_traits/is_same.hpp> |
30 | #include <boost/type_traits/is_const.hpp> |
31 | #include <boost/type_traits/conditional.hpp> |
32 | |
33 | namespace boost |
34 | { |
35 | class any |
36 | { |
37 | public: // structors |
38 | |
39 | BOOST_CONSTEXPR any() BOOST_NOEXCEPT |
40 | : content(0) |
41 | { |
42 | } |
43 | |
44 | template<typename ValueType> |
45 | any(const ValueType & value) |
46 | : content(new holder< |
47 | BOOST_DEDUCED_TYPENAME remove_cv<BOOST_DEDUCED_TYPENAME decay<const ValueType>::type>::type |
48 | >(value)) |
49 | { |
50 | } |
51 | |
52 | any(const any & other) |
53 | : content(other.content ? other.content->clone() : 0) |
54 | { |
55 | } |
56 | |
57 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
58 | // Move constructor |
59 | any(any&& other) BOOST_NOEXCEPT |
60 | : content(other.content) |
61 | { |
62 | other.content = 0; |
63 | } |
64 | |
65 | // Perfect forwarding of ValueType |
66 | template<typename ValueType> |
67 | any(ValueType&& value |
68 | , typename boost::disable_if<boost::is_same<any&, ValueType> >::type* = 0 // disable if value has type `any&` |
69 | , typename boost::disable_if<boost::is_const<ValueType> >::type* = 0) // disable if value has type `const ValueType&&` |
70 | : content(new holder< typename decay<ValueType>::type >(static_cast<ValueType&&>(value))) |
71 | { |
72 | } |
73 | #endif |
74 | |
75 | ~any() BOOST_NOEXCEPT |
76 | { |
77 | delete content; |
78 | } |
79 | |
80 | public: // modifiers |
81 | |
82 | any & swap(any & rhs) BOOST_NOEXCEPT |
83 | { |
84 | placeholder* tmp = content; |
85 | content = rhs.content; |
86 | rhs.content = tmp; |
87 | return *this; |
88 | } |
89 | |
90 | |
91 | #ifdef BOOST_NO_CXX11_RVALUE_REFERENCES |
92 | template<typename ValueType> |
93 | any & operator=(const ValueType & rhs) |
94 | { |
95 | any(rhs).swap(*this); |
96 | return *this; |
97 | } |
98 | |
99 | any & operator=(any rhs) |
100 | { |
101 | rhs.swap(*this); |
102 | return *this; |
103 | } |
104 | |
105 | #else |
106 | any & operator=(const any& rhs) |
107 | { |
108 | any(rhs).swap(rhs&: *this); |
109 | return *this; |
110 | } |
111 | |
112 | // move assignment |
113 | any & operator=(any&& rhs) BOOST_NOEXCEPT |
114 | { |
115 | rhs.swap(rhs&: *this); |
116 | any().swap(rhs); |
117 | return *this; |
118 | } |
119 | |
120 | // Perfect forwarding of ValueType |
121 | template <class ValueType> |
122 | any & operator=(ValueType&& rhs) |
123 | { |
124 | any(static_cast<ValueType&&>(rhs)).swap(rhs&: *this); |
125 | return *this; |
126 | } |
127 | #endif |
128 | |
129 | public: // queries |
130 | |
131 | bool empty() const BOOST_NOEXCEPT |
132 | { |
133 | return !content; |
134 | } |
135 | |
136 | void clear() BOOST_NOEXCEPT |
137 | { |
138 | any().swap(rhs&: *this); |
139 | } |
140 | |
141 | const boost::typeindex::type_info& type() const BOOST_NOEXCEPT |
142 | { |
143 | return content ? content->type() : boost::typeindex::type_id<void>().type_info(); |
144 | } |
145 | |
146 | #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
147 | private: // types |
148 | #else |
149 | public: // types (public so any_cast can be non-friend) |
150 | #endif |
151 | |
152 | class BOOST_SYMBOL_VISIBLE placeholder |
153 | { |
154 | public: // structors |
155 | |
156 | virtual ~placeholder() |
157 | { |
158 | } |
159 | |
160 | public: // queries |
161 | |
162 | virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT = 0; |
163 | |
164 | virtual placeholder * clone() const = 0; |
165 | |
166 | }; |
167 | |
168 | template<typename ValueType> |
169 | class holder |
170 | #ifndef BOOST_NO_CXX11_FINAL |
171 | final |
172 | #endif |
173 | : public placeholder |
174 | { |
175 | public: // structors |
176 | |
177 | holder(const ValueType & value) |
178 | : held(value) |
179 | { |
180 | } |
181 | |
182 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
183 | holder(ValueType&& value) |
184 | : held(static_cast< ValueType&& >(value)) |
185 | { |
186 | } |
187 | #endif |
188 | public: // queries |
189 | |
190 | const boost::typeindex::type_info& type() const BOOST_NOEXCEPT BOOST_OVERRIDE |
191 | { |
192 | return boost::typeindex::type_id<ValueType>().type_info(); |
193 | } |
194 | |
195 | placeholder * clone() const BOOST_OVERRIDE |
196 | { |
197 | return new holder(held); |
198 | } |
199 | |
200 | public: // representation |
201 | |
202 | ValueType held; |
203 | |
204 | private: // intentionally left unimplemented |
205 | holder & operator=(const holder &); |
206 | }; |
207 | |
208 | #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS |
209 | |
210 | private: // representation |
211 | |
212 | template<typename ValueType> |
213 | friend ValueType * any_cast(any *) BOOST_NOEXCEPT; |
214 | |
215 | template<typename ValueType> |
216 | friend ValueType * unsafe_any_cast(any *) BOOST_NOEXCEPT; |
217 | |
218 | #else |
219 | |
220 | public: // representation (public so any_cast can be non-friend) |
221 | |
222 | #endif |
223 | |
224 | placeholder * content; |
225 | |
226 | }; |
227 | |
228 | inline void swap(any & lhs, any & rhs) BOOST_NOEXCEPT |
229 | { |
230 | lhs.swap(rhs); |
231 | } |
232 | |
233 | class BOOST_SYMBOL_VISIBLE bad_any_cast : |
234 | #ifndef BOOST_NO_RTTI |
235 | public std::bad_cast |
236 | #else |
237 | public std::exception |
238 | #endif |
239 | { |
240 | public: |
241 | const char * what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE |
242 | { |
243 | return "boost::bad_any_cast: " |
244 | "failed conversion using boost::any_cast" ; |
245 | } |
246 | }; |
247 | |
248 | template<typename ValueType> |
249 | ValueType * any_cast(any * operand) BOOST_NOEXCEPT |
250 | { |
251 | return operand && operand->type() == boost::typeindex::type_id<ValueType>() |
252 | ? boost::addressof( |
253 | static_cast<any::holder<BOOST_DEDUCED_TYPENAME remove_cv<ValueType>::type> *>(operand->content)->held |
254 | ) |
255 | : 0; |
256 | } |
257 | |
258 | template<typename ValueType> |
259 | inline const ValueType * any_cast(const any * operand) BOOST_NOEXCEPT |
260 | { |
261 | return any_cast<ValueType>(const_cast<any *>(operand)); |
262 | } |
263 | |
264 | template<typename ValueType> |
265 | ValueType any_cast(any & operand) |
266 | { |
267 | typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; |
268 | |
269 | |
270 | nonref * result = any_cast<nonref>(boost::addressof(o&: operand)); |
271 | if(!result) |
272 | boost::throw_exception(e: bad_any_cast()); |
273 | |
274 | // Attempt to avoid construction of a temporary object in cases when |
275 | // `ValueType` is not a reference. Example: |
276 | // `static_cast<std::string>(*result);` |
277 | // which is equal to `std::string(*result);` |
278 | typedef BOOST_DEDUCED_TYPENAME boost::conditional< |
279 | boost::is_reference<ValueType>::value, |
280 | ValueType, |
281 | BOOST_DEDUCED_TYPENAME boost::add_reference<ValueType>::type |
282 | >::type ref_type; |
283 | |
284 | #ifdef BOOST_MSVC |
285 | # pragma warning(push) |
286 | # pragma warning(disable: 4172) // "returning address of local variable or temporary" but *result is not local! |
287 | #endif |
288 | return static_cast<ref_type>(*result); |
289 | #ifdef BOOST_MSVC |
290 | # pragma warning(pop) |
291 | #endif |
292 | } |
293 | |
294 | template<typename ValueType> |
295 | inline ValueType any_cast(const any & operand) |
296 | { |
297 | typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref; |
298 | return any_cast<const nonref &>(const_cast<any &>(operand)); |
299 | } |
300 | |
301 | #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES |
302 | template<typename ValueType> |
303 | inline ValueType any_cast(any&& operand) |
304 | { |
305 | BOOST_STATIC_ASSERT_MSG( |
306 | boost::is_rvalue_reference<ValueType&&>::value /*true if ValueType is rvalue or just a value*/ |
307 | || boost::is_const< typename boost::remove_reference<ValueType>::type >::value, |
308 | "boost::any_cast shall not be used for getting nonconst references to temporary objects" |
309 | ); |
310 | return any_cast<ValueType>(operand); |
311 | } |
312 | #endif |
313 | |
314 | |
315 | // Note: The "unsafe" versions of any_cast are not part of the |
316 | // public interface and may be removed at any time. They are |
317 | // required where we know what type is stored in the any and can't |
318 | // use typeid() comparison, e.g., when our types may travel across |
319 | // different shared libraries. |
320 | template<typename ValueType> |
321 | inline ValueType * unsafe_any_cast(any * operand) BOOST_NOEXCEPT |
322 | { |
323 | return boost::addressof( |
324 | static_cast<any::holder<ValueType> *>(operand->content)->held |
325 | ); |
326 | } |
327 | |
328 | template<typename ValueType> |
329 | inline const ValueType * unsafe_any_cast(const any * operand) BOOST_NOEXCEPT |
330 | { |
331 | return unsafe_any_cast<ValueType>(const_cast<any *>(operand)); |
332 | } |
333 | } |
334 | |
335 | // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. |
336 | // Copyright Antony Polukhin, 2013-2020. |
337 | // |
338 | // Distributed under the Boost Software License, Version 1.0. (See |
339 | // accompanying file LICENSE_1_0.txt or copy at |
340 | // http://www.boost.org/LICENSE_1_0.txt) |
341 | |
342 | #endif |
343 | |