CYCLUS
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 ==============================================================================
14 Boost Software License - Version 1.0 - August 17th, 2003
15 
16 Permission is hereby granted, free of charge, to any person or organization
17 obtaining a copy of the software and accompanying documentation covered by
18 this license (the "Software") to use, reproduce, display, distribute,
19 execute, and transmit the Software, and to prepare derivative works of the
20 Software, and to permit third-parties to whom the Software is furnished to
21 do so, all subject to the following:
22 
23 The copyright notices in the Software and this entire statement, including
24 the above license grant, this restriction and the following disclaimer,
25 must be included in all copies of the Software, in whole or in part, and
26 all derivative works of the Software, unless such copies or derivative
27 works are solely in the form of machine-executable object code generated by
28 a source language processor.
29 
30 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
31 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
32 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
33 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
34 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
35 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
36 DEALINGS IN THE SOFTWARE.
37 ==============================================================================
38 WARNING: this file was modified by Robert Carlsen for Cyclus from the
39 original 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/detail/sp_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 ///////////////////////////////////////////////////////////////////////////////
72 namespace boost { namespace spirit
73 {
74  struct bad_any_cast
75  : std::bad_cast
76  {
77  bad_any_cast(boost::detail::sp_typeinfo const& src, boost::detail::sp_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::detail::sp_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::detail::sp_typeinfo const& get_type()
111  {
112  return BOOST_SP_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::detail::sp_typeinfo const& get_type()
142  {
143  return BOOST_SP_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>
168  struct get_table
169  {
170  typedef mpl::bool_<(sizeof(T) <= sizeof(void*))> is_small;
171 
172  template <typename Char>
173  static fxn_ptr_table<Char>* get()
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  new (&object) T(x);
203  else
204  object = new T(x);
205  }
206 
207  basic_hold_any(const char* x)
208  : table(spirit::detail::get_table< ::std::string>::template get<Char>()), object(0)
209  {
210  new (&object) ::std::string(x);
211  }
212 
214  : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()),
215  object(0)
216  {
217  }
218 
220  : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()),
221  object(0)
222  {
223  assign(x);
224  }
225 
227  {
228  table->static_delete(&object);
229  }
230 
231  // assignment
233  {
234  if (&x != this) {
235  // are we copying between the same type?
236  if (table == x.table) {
237  // if so, we can avoid reallocation
238  table->move(&x.object, &object);
239  }
240  else {
241  reset();
242  x.table->clone(&x.object, &object);
243  table = x.table;
244  }
245  }
246  return *this;
247  }
248 
249  template <typename T>
250  basic_hold_any& assign(T const& x)
251  {
252  // are we copying between the same type?
255  if (table == x_table) {
256  // if so, we can avoid deallocating and re-use memory
257  table->destruct(&object); // first destruct the old content
259  // create copy on-top of object pointer itself
260  new (&object) T(x);
261  }
262  else {
263  // create copy on-top of old version
264  new (object) T(x);
265  }
266  }
267  else {
269  // create copy on-top of object pointer itself
270  table->destruct(&object); // first destruct the old content
271  new (&object) T(x);
272  }
273  else {
274  reset(); // first delete the old content
275  object = new T(x);
276  }
277  table = x_table; // update table pointer
278  }
279  return *this;
280  }
281 
282  // assignment operator
283  template <typename T>
285  {
286  return assign(x);
287  }
288 
289  // assignment operator
291  {
292  return assign(x);
293  }
294 
295  // utility functions
297  {
298  std::swap(table, x.table);
299  std::swap(object, x.object);
300  return *this;
301  }
302 
303  boost::detail::sp_typeinfo const& type() const
304  {
305  return table->get_type();
306  }
307 
308  template <typename T>
309  T const& cast() const
310  {
311  if (type() != BOOST_SP_TYPEID(T))
312  throw bad_any_cast(type(), BOOST_SP_TYPEID(T));
313 
315  *reinterpret_cast<T const*>(&object) :
316  *reinterpret_cast<T const*>(object);
317  }
318 
319  const void* castsmallvoid() const
320  {
321  return &object;
322  }
323 
324 // implicit casting is disabled by default for compatibility with boost::any
325 #ifdef BOOST_SPIRIT_ANY_IMPLICIT_CASTING
326  // automatic casting operator
327  template <typename T>
328  operator T const& () const { return cast<T>(); }
329 #endif // implicit casting
330 
331  bool empty() const
332  {
334  }
335 
336  void reset()
337  {
338  if (!empty())
339  {
340  table->static_delete(&object);
342  object = 0;
343  }
344  }
345 
346 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
347  private: // types
348  template <typename T, typename Char_>
349  friend T* any_cast(basic_hold_any<Char_> *);
350 #else
351  public: // types (public so any_cast can be non-friend)
352 #endif
353  // fields
355  void* object;
356  };
357 
358  // boost::any-like casting
359  template <typename T, typename Char>
360  inline T* any_cast (basic_hold_any<Char>* operand)
361  {
362  if (operand && operand->type() == BOOST_SP_TYPEID(T)) {
364  reinterpret_cast<T*>(&operand->object) :
365  reinterpret_cast<T*>(operand->object);
366  }
367  return 0;
368  }
369 
370  template <typename T, typename Char>
371  inline T const* any_cast(basic_hold_any<Char> const* operand)
372  {
373  return any_cast<T>(const_cast<basic_hold_any<Char>*>(operand));
374  }
375 
376  template <typename T, typename Char>
378  {
379  typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
380 
381 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
382  // If 'nonref' is still reference type, it means the user has not
383  // specialized 'remove_reference'.
384 
385  // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
386  // to generate specialization of remove_reference for your class
387  // See type traits library documentation for details
388  BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
389 #endif
390 
391  nonref* result = any_cast<nonref>(&operand);
392  if(!result)
393  boost::throw_exception(bad_any_cast(operand.type(), BOOST_SP_TYPEID(T)));
394  return *result;
395  }
396 
397  template <typename T, typename Char>
398  T const& any_cast(basic_hold_any<Char> const& operand)
399  {
400  typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
401 
402 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
403  // The comment in the above version of 'any_cast' explains when this
404  // assert is fired and what to do.
405  BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
406 #endif
407 
408  return any_cast<nonref const&>(const_cast<basic_hold_any<Char> &>(operand));
409  }
410 
411  ///////////////////////////////////////////////////////////////////////////////
412  // backwards compatibility
415 
416  namespace traits
417  {
418  template <typename T>
419  struct is_hold_any : mpl::false_ {};
420 
421  template <typename Char>
422  struct is_hold_any<basic_hold_any<Char> > : mpl::true_ {};
423  }
424 
425 }} // namespace boost::spirit
426 
427 ///////////////////////////////////////////////////////////////////////////////
428 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
429 # pragma warning(pop)
430 #endif
431 
432 #endif
basic_hold_any(T const &x)
Definition: any.hpp:198
basic_hold_any< wchar_t > whold_any
Definition: any.hpp:414
Definition: any.hpp:72
const void * castsmallvoid() const
Definition: any.hpp:319
boost::detail::sp_typeinfo const & type() const
Definition: any.hpp:303
static void move(void *const *src, void **dest)
Definition: any.hpp:159
basic_hold_any & operator=(basic_hold_any const &x)
Definition: any.hpp:290
static void clone(void *const *src, void **dest)
Definition: any.hpp:122
std::string name(int nuc)
Definition: pyne.cc:2940
basic_hold_any & operator=(T const &x)
Definition: any.hpp:284
basic_hold_any(basic_hold_any const &x)
Definition: any.hpp:219
basic_hold_any & assign(basic_hold_any const &x)
Definition: any.hpp:232
basic_hold_any & assign(T const &x)
Definition: any.hpp:250
static void move(void *const *src, void **dest)
Definition: any.hpp:126
static void clone(void *const *src, void **dest)
Definition: any.hpp:155
basic_hold_any(const char *x)
Definition: any.hpp:207
basic_hold_any< char > hold_any
Definition: any.hpp:413
bad_any_cast(boost::detail::sp_typeinfo const &src, boost::detail::sp_typeinfo const &dest)
Definition: any.hpp:77
T * any_cast(basic_hold_any< Char > *operand)
Definition: any.hpp:360
static boost::detail::sp_typeinfo const & get_type()
Definition: any.hpp:110
static boost::detail::sp_typeinfo const & get_type()
Definition: any.hpp:141
virtual const char * what() const
Definition: any.hpp:81
T const & cast() const
Definition: any.hpp:309
mpl::bool_<(sizeof(T)<=sizeof(void *))> is_small
Definition: any.hpp:170
const char * from
Definition: any.hpp:83
basic_hold_any & swap(basic_hold_any &x)
Definition: any.hpp:296