CYCLUS
Loading...
Searching...
No Matches
any.hpp
Go to the documentation of this file.
1/*=============================================================================
2 Copyright (c) 2007-2011 Hartmut Kaiser
3 Copyright (c) Christopher Diggins 2005
4 Copyright (c) Pablo Aguilar 2005
5 Copyright (c) Kevlin Henney 2001
6
7 Distributed under the Boost Software License, Version 1.0. (See accompanying
8 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9
10 The class boost::spirit::hold_any is built based on the any class
11 published here: http://www.codeproject.com/cpp/dynamic_typing.asp. It adds
12 support for std streaming operator<<() and operator>>().
13==============================================================================
14Boost Software License - Version 1.0 - August 17th, 2003
15
16Permission is hereby granted, free of charge, to any person or organization
17obtaining a copy of the software and accompanying documentation covered by
18this license (the "Software") to use, reproduce, display, distribute,
19execute, and transmit the Software, and to prepare derivative works of the
20Software, and to permit third-parties to whom the Software is furnished to
21do so, all subject to the following:
22
23The copyright notices in the Software and this entire statement, including
24the above license grant, this restriction and the following disclaimer,
25must be included in all copies of the Software, in whole or in part, and
26all derivative works of the Software, unless such copies or derivative
27works are solely in the form of machine-executable object code generated by
28a source language processor.
29
30THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
33SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
34FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
35ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36DEALINGS IN THE SOFTWARE.
37==============================================================================
38WARNING: this file was modified by Robert Carlsen for Cyclus from the
39original Boost 1.54.0
40(http://www.boost.org/doc/libs/1_54_0/boost/spirit/home/support/detail/hold_any.hpp).
41==============================================================================*/
42#if !defined(BOOST_SPIRIT_HOLD_ANY_MAY_02_2007_0857AM)
43#define BOOST_SPIRIT_HOLD_ANY_MAY_02_2007_0857AM
44
45#if defined(_MSC_VER)
46#pragma once
47#endif
48
49#include <boost/config.hpp>
50#include <boost/type_traits/remove_reference.hpp>
51#include <boost/type_traits/is_reference.hpp>
52#include <boost/throw_exception.hpp>
53#include <boost/static_assert.hpp>
54#include <boost/mpl/bool.hpp>
55#include <boost/assert.hpp>
56#include <boost/core/typeinfo.hpp>
57
58#include <stdexcept>
59#include <typeinfo>
60#include <algorithm>
61#include <iosfwd>
62#include <string>
63
64///////////////////////////////////////////////////////////////////////////////
65#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
66# pragma warning(push)
67# pragma warning(disable: 4100) // 'x': unreferenced formal parameter
68# pragma warning(disable: 4127) // conditional expression is constant
69#endif
70
71///////////////////////////////////////////////////////////////////////////////
72namespace boost { namespace spirit
73{
75 : std::bad_cast
76 {
77 bad_any_cast(boost::core::typeinfo const& src, boost::core::typeinfo const& dest)
78 : from(src.name()), to(dest.name())
79 {}
80
81 virtual const char* what() const throw() { return "bad any cast"; }
82
83 const char* from;
84 const char* to;
85 };
86
87 namespace detail
88 {
89 // function pointer table
90 template <typename Char>
92 {
93 boost::core::typeinfo const& (*get_type)();
94 void (*static_delete)(void**);
95 void (*destruct)(void**);
96 void (*clone)(void* const*, void**);
97 void (*move)(void* const*, void**);
98 };
99
100 // static functions for small value-types
101 template <typename Small>
102 struct fxns;
103
104 template <>
105 struct fxns<mpl::true_>
106 {
107 template<typename T, typename Char>
108 struct type
109 {
110 static boost::core::typeinfo const& get_type()
111 {
112 return BOOST_CORE_TYPEID(T);
113 }
114 static void static_delete(void** x)
115 {
116 reinterpret_cast<T*>(x)->~T();
117 }
118 static void destruct(void** x)
119 {
120 reinterpret_cast<T*>(x)->~T();
121 }
122 static void clone(void* const* src, void** dest)
123 {
124 new (dest) T(*reinterpret_cast<T const*>(src));
125 }
126 static void move(void* const* src, void** dest)
127 {
128 *reinterpret_cast<T*>(dest) =
129 *reinterpret_cast<T const*>(src);
130 }
131 };
132 };
133
134 // static functions for big value-types (bigger than a void*)
135 template <>
136 struct fxns<mpl::false_>
137 {
138 template<typename T, typename Char>
139 struct type
140 {
141 static boost::core::typeinfo const& get_type()
142 {
143 return BOOST_CORE_TYPEID(T);
144 }
145 static void static_delete(void** x)
146 {
147 // destruct and free memory
148 delete (*reinterpret_cast<T**>(x));
149 }
150 static void destruct(void** x)
151 {
152 // destruct only, we'll reuse memory
153 (*reinterpret_cast<T**>(x))->~T();
154 }
155 static void clone(void* const* src, void** dest)
156 {
157 *dest = new T(**reinterpret_cast<T* const*>(src));
158 }
159 static void move(void* const* src, void** dest)
160 {
161 **reinterpret_cast<T**>(dest) =
162 **reinterpret_cast<T* const*>(src);
163 }
164 };
165 };
166
167 template <typename T>
169 {
170 typedef mpl::bool_<(sizeof(T) <= sizeof(void*))> is_small;
171
172 template <typename Char>
174 {
175 static fxn_ptr_table<Char> static_table =
176 {
177 fxns<is_small>::template type<T, Char>::get_type,
178 fxns<is_small>::template type<T, Char>::static_delete,
179 fxns<is_small>::template type<T, Char>::destruct,
180 fxns<is_small>::template type<T, Char>::clone,
181 fxns<is_small>::template type<T, Char>::move,
182 };
183 return &static_table;
184 }
185 };
186
187 ///////////////////////////////////////////////////////////////////////
188 struct empty {};
189 }
190
191 ///////////////////////////////////////////////////////////////////////////
192 template <typename Char>
194 {
195 public:
196 // constructors
197 template <typename T>
198 basic_hold_any(T const& x)
199 : table(spirit::detail::get_table<T>::template get<Char>()), object(0)
200 {
202 }
203
204 basic_hold_any(const char* x)
205 : table(spirit::detail::get_table< ::std::string>::template get<Char>()), object(0)
206 {
207 new (&object) ::std::string(x);
208 }
209
211 : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()),
212 object(0)
213 {
214 }
215
217 : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()),
218 object(0)
219 {
220 assign(x);
221 }
222
224 {
225 table->static_delete(&object);
226 }
227
228 template <typename T>
229 static void new_object(void*& object, T const& x, mpl::true_)
230 {
231 new (&object) T(x);
232 }
233
234 template <typename T>
235 static void new_object(void*& object, T const& x, mpl::false_)
236 {
237 object = new T(x);
238 }
239 // assignment
241 {
242 if (&x != this) {
243 // are we copying between the same type?
244 if (table == x.table) {
245 // if so, we can avoid reallocation
246 table->move(&x.object, &object);
247 }
248 else {
249 reset();
250 x.table->clone(&x.object, &object);
251 table = x.table;
252 }
253 }
254 return *this;
255 }
256
257 template <typename T>
259 {
260 // are we copying between the same type?
263 if (table == x_table) {
264 // if so, we can avoid deallocating and re-use memory
265 table->destruct(&object); // first destruct the old content
267 }
268 else {
270 // create copy on-top of object pointer itself
271 table->destruct(&object); // first destruct the old content
273 }
274 else {
275 reset(); // first delete the old content
277 }
278 table = x_table; // update table pointer
279 }
280 return *this;
281 }
282
283 // assignment operator
284 template <typename T>
286 {
287 return assign(x);
288 }
289
290 // assignment operator
292 {
293 return assign(x);
294 }
295
296 // utility functions
298 {
299 std::swap(table, x.table);
300 std::swap(object, x.object);
301 return *this;
302 }
303
304 boost::core::typeinfo const& type() const
305 {
306 return table->get_type();
307 }
308
309 template <typename T>
310 T const& cast() const
311 {
312 if (type() != BOOST_CORE_TYPEID(T))
313 throw bad_any_cast(type(), BOOST_CORE_TYPEID(T));
314
316 *reinterpret_cast<T const*>(&object) :
317 *reinterpret_cast<T const*>(object);
318 }
319
320 const void* castsmallvoid() const
321 {
322 return &object;
323 }
324
325// implicit casting is disabled by default for compatibility with boost::any
326#ifdef BOOST_SPIRIT_ANY_IMPLICIT_CASTING
327 // automatic casting operator
328 template <typename T>
329 operator T const& () const { return cast<T>(); }
330#endif // implicit casting
331
332 bool empty() const
333 {
335 }
336
337 void reset()
338 {
339 if (!empty())
340 {
341 table->static_delete(&object);
343 object = 0;
344 }
345 }
346
347#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
348 private: // types
349 template <typename T, typename Char_>
351#else
352 public: // types (public so any_cast can be non-friend)
353#endif
354 // fields
356 void* object;
357 };
358
359 // boost::any-like casting
360 template <typename T, typename Char>
361 inline T* any_cast (basic_hold_any<Char>* operand)
362 {
363 if (operand && operand->type() == BOOST_CORE_TYPEID(T)) {
365 reinterpret_cast<T*>(&operand->object) :
366 reinterpret_cast<T*>(operand->object);
367 }
368 return 0;
369 }
370
371 template <typename T, typename Char>
372 inline T const* any_cast(basic_hold_any<Char> const* operand)
373 {
374 return any_cast<T>(const_cast<basic_hold_any<Char>*>(operand));
375 }
376
377 template <typename T, typename Char>
379 {
380 typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
381
382#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
383 // If 'nonref' is still reference type, it means the user has not
384 // specialized 'remove_reference'.
385
386 // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
387 // to generate specialization of remove_reference for your class
388 // See type traits library documentation for details
389 BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
390#endif
391
392 nonref* result = any_cast<nonref>(&operand);
393 if(!result)
394 boost::throw_exception(bad_any_cast(operand.type(), BOOST_CORE_TYPEID(T)));
395 return *result;
396 }
397
398 template <typename T, typename Char>
399 T const& any_cast(basic_hold_any<Char> const& operand)
400 {
401 typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
402
403#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
404 // The comment in the above version of 'any_cast' explains when this
405 // assert is fired and what to do.
406 BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
407#endif
408
409 return any_cast<nonref const&>(const_cast<basic_hold_any<Char> &>(operand));
410 }
411
412 ///////////////////////////////////////////////////////////////////////////////
413 // backwards compatibility
416
417 namespace traits
418 {
419 template <typename T>
420 struct is_hold_any : mpl::false_ {};
421
422 template <typename Char>
423 struct is_hold_any<basic_hold_any<Char> > : mpl::true_ {};
424 }
425
426}} // namespace boost::spirit
427
428///////////////////////////////////////////////////////////////////////////////
429#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
430# pragma warning(pop)
431#endif
432
433#endif
basic_hold_any & operator=(basic_hold_any const &x)
Definition any.hpp:291
T const & cast() const
Definition any.hpp:310
basic_hold_any & operator=(T const &x)
Definition any.hpp:285
const void * castsmallvoid() const
Definition any.hpp:320
basic_hold_any(basic_hold_any const &x)
Definition any.hpp:216
basic_hold_any & swap(basic_hold_any &x)
Definition any.hpp:297
basic_hold_any & assign(T const &x)
Definition any.hpp:258
static void new_object(void *&object, T const &x, mpl::true_)
Definition any.hpp:229
basic_hold_any & assign(basic_hold_any const &x)
Definition any.hpp:240
static void new_object(void *&object, T const &x, mpl::false_)
Definition any.hpp:235
boost::core::typeinfo const & type() const
Definition any.hpp:304
friend T * any_cast(basic_hold_any< Char_ > *)
basic_hold_any(const char *x)
Definition any.hpp:204
basic_hold_any< wchar_t > whold_any
Definition any.hpp:415
basic_hold_any< char > hold_any
Definition any.hpp:414
T * any_cast(basic_hold_any< Char > *operand)
Definition any.hpp:361
Definition any.hpp:72
bad_any_cast(boost::core::typeinfo const &src, boost::core::typeinfo const &dest)
Definition any.hpp:77
virtual const char * what() const
Definition any.hpp:81
void(* static_delete)(void **)
Definition any.hpp:94
void(* move)(void *const *, void **)
Definition any.hpp:97
void(* clone)(void *const *, void **)
Definition any.hpp:96
static boost::core::typeinfo const & get_type()
Definition any.hpp:141
static void move(void *const *src, void **dest)
Definition any.hpp:159
static void clone(void *const *src, void **dest)
Definition any.hpp:155
static void move(void *const *src, void **dest)
Definition any.hpp:126
static void clone(void *const *src, void **dest)
Definition any.hpp:122
static boost::core::typeinfo const & get_type()
Definition any.hpp:110
static fxn_ptr_table< Char > * get()
Definition any.hpp:173
mpl::bool_<(sizeof(T)<=sizeof(void *)) is_small)
Definition any.hpp:170