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 
any()40         any() BOOST_NOEXCEPT
41           : content(0)
42         {
43         }
44 
45         template<typename ValueType>
any(const ValueType & value)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 
any(const any & other)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
any(any && other)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>
any(ValueType && value,typename boost::disable_if<boost::is_same<any &,ValueType>>::type * =0,typename boost::disable_if<boost::is_const<ValueType>>::type * =0)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 
~any()76         ~any() BOOST_NOEXCEPT
77         {
78             delete content;
79         }
80 
81     public: // modifiers
82 
swap(any & rhs)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>
operator =(const ValueType & rhs)92         any & operator=(const ValueType & rhs)
93         {
94             any(rhs).swap(*this);
95             return *this;
96         }
97 
operator =(any rhs)98         any & operator=(any rhs)
99         {
100             any(rhs).swap(*this);
101             return *this;
102         }
103 
104 #else
operator =(const any & rhs)105         any & operator=(const any& rhs)
106         {
107             any(rhs).swap(*this);
108             return *this;
109         }
110 
111         // move assignement
operator =(any && rhs)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>
operator =(ValueType && rhs)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 
empty() const130         bool empty() const BOOST_NOEXCEPT
131         {
132             return !content;
133         }
134 
clear()135         void clear() BOOST_NOEXCEPT
136         {
137             any().swap(*this);
138         }
139 
type() const140         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 
~placeholder()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 
holder(const ValueType & value)172             holder(const ValueType & value)
173               : held(value)
174             {
175             }
176 
177 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
holder(ValueType && value)178             holder(ValueType&& value)
179               : held(static_cast< ValueType&& >(value))
180             {
181             }
182 #endif
183         public: // queries
184 
type() const185             virtual const boost::typeindex::type_info& type() const BOOST_NOEXCEPT
186             {
187                 return boost::typeindex::type_id<ValueType>().type_info();
188             }
189 
clone() const190             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 
swap(any & lhs,any & rhs)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:
what() const236         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>
any_cast(any * operand)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>
any_cast(const any * operand)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>
any_cast(any & operand)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>
any_cast(const any & operand)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>
any_cast(any && operand)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>
unsafe_any_cast(any * operand)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>
unsafe_any_cast(const any * operand)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