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