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 {
73namespace spirit {
74struct bad_any_cast : std::bad_cast {
75 bad_any_cast(boost::core::typeinfo const& src,
76 boost::core::typeinfo const& dest)
77 : from(src.name()), to(dest.name()) {}
78
79 virtual const char* what() const throw() { return "bad any cast"; }
80
81 const char* from;
82 const char* to;
83};
84
85namespace detail {
86// function pointer table
87template <typename Char> struct fxn_ptr_table {
88 boost::core::typeinfo const& (*get_type)();
89 void (*static_delete)(void**);
90 void (*destruct)(void**);
91 void (*clone)(void* const*, void**);
92 void (*move)(void* const*, void**);
93};
94
95// static functions for small value-types
96template <typename Small> struct fxns;
97
98template <> struct fxns<mpl::true_> {
99 template <typename T, typename Char> struct type {
100 static boost::core::typeinfo const& get_type() {
101 return BOOST_CORE_TYPEID(T);
102 }
103 static void static_delete(void** x) { reinterpret_cast<T*>(x)->~T(); }
104 static void destruct(void** x) { reinterpret_cast<T*>(x)->~T(); }
105 static void clone(void* const* src, void** dest) {
106 new (dest) T(*reinterpret_cast<T const*>(src));
107 }
108 static void move(void* const* src, void** dest) {
109 *reinterpret_cast<T*>(dest) = *reinterpret_cast<T const*>(src);
110 }
111 };
112};
113
114// static functions for big value-types (bigger than a void*)
115template <> struct fxns<mpl::false_> {
116 template <typename T, typename Char> struct type {
117 static boost::core::typeinfo const& get_type() {
118 return BOOST_CORE_TYPEID(T);
119 }
120 static void static_delete(void** x) {
121 // destruct and free memory
122 delete (*reinterpret_cast<T**>(x));
123 }
124 static void destruct(void** x) {
125 // destruct only, we'll reuse memory
126 (*reinterpret_cast<T**>(x))->~T();
127 }
128 static void clone(void* const* src, void** dest) {
129 *dest = new T(**reinterpret_cast<T* const*>(src));
130 }
131 static void move(void* const* src, void** dest) {
132 **reinterpret_cast<T**>(dest) = **reinterpret_cast<T* const*>(src);
133 }
134 };
135};
136
137template <typename T> struct get_table {
138 typedef mpl::bool_<(sizeof(T) <= sizeof(void*))> is_small;
139
140 template <typename Char> static fxn_ptr_table<Char>* get() {
141 static fxn_ptr_table<Char> static_table = {
142 fxns<is_small>::template type<T, Char>::get_type,
143 fxns<is_small>::template type<T, Char>::static_delete,
144 fxns<is_small>::template type<T, Char>::destruct,
145 fxns<is_small>::template type<T, Char>::clone,
146 fxns<is_small>::template type<T, Char>::move,
147 };
148 return &static_table;
149 }
150};
151
152///////////////////////////////////////////////////////////////////////
153struct empty {};
154} // namespace detail
155
156///////////////////////////////////////////////////////////////////////////
157template <typename Char> class basic_hold_any {
158 public:
159 // constructors
160 template <typename T>
161 basic_hold_any(T const& x)
162 : table(spirit::detail::get_table<T>::template get<Char>()), object(0) {
164 }
165
166 basic_hold_any(const char* x)
167 : table(spirit::detail::get_table<::std::string>::template get<Char>()),
168 object(0) {
169 new (&object)::std::string(x);
170 }
171
173 : table(spirit::detail::get_table<spirit::detail::empty>::template get<
174 Char>()),
175 object(0) {}
176
178 : table(spirit::detail::get_table<spirit::detail::empty>::template get<
179 Char>()),
180 object(0) {
181 assign(x);
182 }
183
184 ~basic_hold_any() { table->static_delete(&object); }
185
186 template <typename T>
187 static void new_object(void*& object, T const& x, mpl::true_) {
188 new (&object) T(x);
189 }
190
191 template <typename T>
192 static void new_object(void*& object, T const& x, mpl::false_) {
193 object = new T(x);
194 }
195 // assignment
197 if (&x != this) {
198 // are we copying between the same type?
199 if (table == x.table) {
200 // if so, we can avoid reallocation
201 table->move(&x.object, &object);
202 } else {
203 reset();
204 x.table->clone(&x.object, &object);
205 table = x.table;
206 }
207 }
208 return *this;
209 }
210
211 template <typename T> basic_hold_any& assign(T const& x) {
212 // are we copying between the same type?
215 if (table == x_table) {
216 // if so, we can avoid deallocating and re-use memory
217 table->destruct(&object); // first destruct the old content
219 } else {
221 // create copy on-top of object pointer itself
222 table->destruct(&object); // first destruct the old content
223 new_object(object, x,
225 } else {
226 reset(); // first delete the old content
227 new_object(object, x,
229 }
230 table = x_table; // update table pointer
231 }
232 return *this;
233 }
234
235 // assignment operator
236 template <typename T> basic_hold_any& operator=(T const& x) {
237 return assign(x);
238 }
239
240 // assignment operator
242
243 // utility functions
245 std::swap(table, x.table);
246 std::swap(object, x.object);
247 return *this;
248 }
249
250 boost::core::typeinfo const& type() const { return table->get_type(); }
251
252 template <typename T> T const& cast() const {
253 if (type() != BOOST_CORE_TYPEID(T))
254 throw bad_any_cast(type(), BOOST_CORE_TYPEID(T));
255
257 ? *reinterpret_cast<T const*>(&object)
258 : *reinterpret_cast<T const*>(object);
259 }
260
261 const void* castsmallvoid() const { return &object; }
262
263// implicit casting is disabled by default for compatibility with boost::any
264#ifdef BOOST_SPIRIT_ANY_IMPLICIT_CASTING
265 // automatic casting operator
266 template <typename T> operator T const&() const { return cast<T>(); }
267#endif // implicit casting
268
269 bool empty() const {
270 return table == spirit::detail::get_table<
271 spirit::detail::empty>::template get<Char>();
272 }
273
274 void reset() {
275 if (!empty()) {
276 table->static_delete(&object);
278 Char>();
279 object = 0;
280 }
281 }
282
283#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
284 private: // types
285 template <typename T, typename Char_>
287#else
288 public: // types (public so any_cast can be non-friend)
289#endif
290 // fields
292 void* object;
293};
294
295// boost::any-like casting
296template <typename T, typename Char>
297inline T* any_cast(basic_hold_any<Char>* operand) {
298 if (operand && operand->type() == BOOST_CORE_TYPEID(T)) {
300 ? reinterpret_cast<T*>(&operand->object)
301 : reinterpret_cast<T*>(operand->object);
302 }
303 return 0;
304}
305
306template <typename T, typename Char>
307inline T const* any_cast(basic_hold_any<Char> const* operand) {
308 return any_cast<T>(const_cast<basic_hold_any<Char>*>(operand));
309}
310
311template <typename T, typename Char> T any_cast(basic_hold_any<Char>& operand) {
312 typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
313
314#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
315 // If 'nonref' is still reference type, it means the user has not
316 // specialized 'remove_reference'.
317
318 // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
319 // to generate specialization of remove_reference for your class
320 // See type traits library documentation for details
321 BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
322#endif
323
324 nonref* result = any_cast<nonref>(&operand);
325 if (!result)
326 boost::throw_exception(bad_any_cast(operand.type(), BOOST_CORE_TYPEID(T)));
327 return *result;
328}
329
330template <typename T, typename Char>
331T const& any_cast(basic_hold_any<Char> const& operand) {
332 typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
333
334#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
335 // The comment in the above version of 'any_cast' explains when this
336 // assert is fired and what to do.
337 BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
338#endif
339
340 return any_cast<nonref const&>(const_cast<basic_hold_any<Char>&>(operand));
341}
342
343///////////////////////////////////////////////////////////////////////////////
344// backwards compatibility
347
348namespace traits {
349template <typename T> struct is_hold_any : mpl::false_ {};
350
351template <typename Char>
352struct is_hold_any<basic_hold_any<Char>> : mpl::true_ {};
353} // namespace traits
354
355} // namespace spirit
356} // namespace boost
357
358///////////////////////////////////////////////////////////////////////////////
359#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
360#pragma warning(pop)
361#endif
362
363#endif
basic_hold_any & operator=(basic_hold_any const &x)
Definition any.hpp:241
T const & cast() const
Definition any.hpp:252
basic_hold_any & operator=(T const &x)
Definition any.hpp:236
const void * castsmallvoid() const
Definition any.hpp:261
basic_hold_any(basic_hold_any const &x)
Definition any.hpp:177
basic_hold_any & swap(basic_hold_any &x)
Definition any.hpp:244
basic_hold_any & assign(T const &x)
Definition any.hpp:211
static void new_object(void *&object, T const &x, mpl::true_)
Definition any.hpp:187
basic_hold_any & assign(basic_hold_any const &x)
Definition any.hpp:196
static void new_object(void *&object, T const &x, mpl::false_)
Definition any.hpp:192
boost::core::typeinfo const & type() const
Definition any.hpp:250
friend T * any_cast(basic_hold_any< Char_ > *)
basic_hold_any(const char *x)
Definition any.hpp:166
basic_hold_any< wchar_t > whold_any
Definition any.hpp:346
basic_hold_any< char > hold_any
Definition any.hpp:345
T * any_cast(basic_hold_any< Char > *operand)
Definition any.hpp:297
Definition any.hpp:72
bad_any_cast(boost::core::typeinfo const &src, boost::core::typeinfo const &dest)
Definition any.hpp:75
virtual const char * what() const
Definition any.hpp:79
void(* static_delete)(void **)
Definition any.hpp:89
void(* move)(void *const *, void **)
Definition any.hpp:92
void(* clone)(void *const *, void **)
Definition any.hpp:91
static boost::core::typeinfo const & get_type()
Definition any.hpp:117
static void move(void *const *src, void **dest)
Definition any.hpp:131
static void clone(void *const *src, void **dest)
Definition any.hpp:128
static void move(void *const *src, void **dest)
Definition any.hpp:108
static void clone(void *const *src, void **dest)
Definition any.hpp:105
static boost::core::typeinfo const & get_type()
Definition any.hpp:100
static fxn_ptr_table< Char > * get()
Definition any.hpp:140
mpl::bool_<(sizeof(T)<=sizeof(void *))> is_small
Definition any.hpp:138