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