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