]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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(content, 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(*this); | |
108 | return *this; | |
109 | } | |
110 | ||
111 | // move assignement | |
112 | any & operator=(any&& rhs) BOOST_NOEXCEPT | |
113 | { | |
114 | rhs.swap(*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(*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(*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(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 |