File indexing completed on 2025-01-19 09:47:51
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #if !defined(BOOST_SPIRIT_HOLD_ANY_MAY_02_2007_0857AM)
0015 #define BOOST_SPIRIT_HOLD_ANY_MAY_02_2007_0857AM
0016
0017 #if defined(_MSC_VER)
0018 #pragma once
0019 #endif
0020
0021 #include <boost/config.hpp>
0022 #include <boost/type_traits/remove_reference.hpp>
0023 #include <boost/type_traits/is_reference.hpp>
0024 #include <boost/throw_exception.hpp>
0025 #include <boost/static_assert.hpp>
0026 #include <boost/mpl/bool.hpp>
0027 #include <boost/assert.hpp>
0028 #include <boost/core/typeinfo.hpp>
0029
0030 #include <algorithm>
0031 #include <iosfwd>
0032 #include <stdexcept>
0033 #include <typeinfo>
0034
0035
0036 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0037 # pragma warning(push)
0038 # pragma warning(disable: 4100)
0039 # pragma warning(disable: 4127)
0040 #endif
0041
0042
0043 namespace boost { namespace spirit
0044 {
0045 struct bad_any_cast
0046 : std::bad_cast
0047 {
0048 bad_any_cast(boost::core::typeinfo const& src, boost::core::typeinfo const& dest)
0049 : from(src.name()), to(dest.name())
0050 {}
0051
0052 const char* what() const BOOST_NOEXCEPT_OR_NOTHROW BOOST_OVERRIDE
0053 {
0054 return "bad any cast";
0055 }
0056
0057 const char* from;
0058 const char* to;
0059 };
0060
0061 namespace detail
0062 {
0063
0064 template <typename Char>
0065 struct fxn_ptr_table
0066 {
0067 boost::core::typeinfo const& (*get_type)();
0068 void (*static_delete)(void**);
0069 void (*destruct)(void**);
0070 void (*clone)(void* const*, void**);
0071 void (*move)(void* const*, void**);
0072 std::basic_istream<Char>& (*stream_in)(std::basic_istream<Char>&, void**);
0073 std::basic_ostream<Char>& (*stream_out)(std::basic_ostream<Char>&, void* const*);
0074 };
0075
0076
0077 template <typename Small>
0078 struct fxns;
0079
0080 template <>
0081 struct fxns<mpl::true_>
0082 {
0083 template<typename T, typename Char>
0084 struct type
0085 {
0086 static boost::core::typeinfo const& get_type()
0087 {
0088 return BOOST_CORE_TYPEID(T);
0089 }
0090 static void static_delete(void** x)
0091 {
0092 reinterpret_cast<T*>(x)->~T();
0093 }
0094 static void destruct(void** x)
0095 {
0096 reinterpret_cast<T*>(x)->~T();
0097 }
0098 static void clone(void* const* src, void** dest)
0099 {
0100 new (dest) T(*reinterpret_cast<T const*>(src));
0101 }
0102 static void move(void* const* src, void** dest)
0103 {
0104 *reinterpret_cast<T*>(dest) =
0105 *reinterpret_cast<T const*>(src);
0106 }
0107 static std::basic_istream<Char>&
0108 stream_in (std::basic_istream<Char>& i, void** obj)
0109 {
0110 i >> *reinterpret_cast<T*>(obj);
0111 return i;
0112 }
0113 static std::basic_ostream<Char>&
0114 stream_out(std::basic_ostream<Char>& o, void* const* obj)
0115 {
0116 o << *reinterpret_cast<T const*>(obj);
0117 return o;
0118 }
0119 };
0120 };
0121
0122
0123 template <>
0124 struct fxns<mpl::false_>
0125 {
0126 template<typename T, typename Char>
0127 struct type
0128 {
0129 static boost::core::typeinfo const& get_type()
0130 {
0131 return BOOST_CORE_TYPEID(T);
0132 }
0133 static void static_delete(void** x)
0134 {
0135
0136 delete static_cast<T*>(*x);
0137 }
0138 static void destruct(void** x)
0139 {
0140
0141 static_cast<T*>(*x)->~T();
0142 }
0143 static void clone(void* const* src, void** dest)
0144 {
0145 *dest = new T(*static_cast<T const*>(*src));
0146 }
0147 static void move(void* const* src, void** dest)
0148 {
0149 *static_cast<T*>(*dest) =
0150 *static_cast<T const*>(*src);
0151 }
0152 static std::basic_istream<Char>&
0153 stream_in(std::basic_istream<Char>& i, void** obj)
0154 {
0155 i >> *static_cast<T*>(*obj);
0156 return i;
0157 }
0158 static std::basic_ostream<Char>&
0159 stream_out(std::basic_ostream<Char>& o, void* const* obj)
0160 {
0161 o << *static_cast<T const*>(*obj);
0162 return o;
0163 }
0164 };
0165 };
0166
0167 template <typename T>
0168 struct get_table
0169 {
0170 typedef mpl::bool_<(sizeof(T) <= sizeof(void*))> is_small;
0171
0172 template <typename Char>
0173 static fxn_ptr_table<Char>* get()
0174 {
0175 static fxn_ptr_table<Char> static_table =
0176 {
0177 fxns<is_small>::template type<T, Char>::get_type,
0178 fxns<is_small>::template type<T, Char>::static_delete,
0179 fxns<is_small>::template type<T, Char>::destruct,
0180 fxns<is_small>::template type<T, Char>::clone,
0181 fxns<is_small>::template type<T, Char>::move,
0182 fxns<is_small>::template type<T, Char>::stream_in,
0183 fxns<is_small>::template type<T, Char>::stream_out
0184 };
0185 return &static_table;
0186 }
0187 };
0188
0189
0190 struct empty {};
0191
0192 template <typename Char>
0193 inline std::basic_istream<Char>&
0194 operator>> (std::basic_istream<Char>& i, empty&)
0195 {
0196
0197
0198
0199
0200
0201
0202
0203
0204 BOOST_ASSERT(false &&
0205 "Tried to insert from a std istream into an empty "
0206 "hold_any instance");
0207 return i;
0208 }
0209
0210 template <typename Char>
0211 inline std::basic_ostream<Char>&
0212 operator<< (std::basic_ostream<Char>& o, empty const&)
0213 {
0214 return o;
0215 }
0216 }
0217
0218
0219 template <typename Char>
0220 class basic_hold_any
0221 {
0222 public:
0223
0224 template <typename T>
0225 explicit basic_hold_any(T const& x)
0226 : table(spirit::detail::get_table<T>::template get<Char>()), object(0)
0227 {
0228 new_object(object, x,
0229 typename spirit::detail::get_table<T>::is_small());
0230 }
0231
0232 basic_hold_any()
0233 : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()),
0234 object(0)
0235 {
0236 }
0237
0238 basic_hold_any(basic_hold_any const& x)
0239 : table(spirit::detail::get_table<spirit::detail::empty>::template get<Char>()),
0240 object(0)
0241 {
0242 assign(x);
0243 }
0244
0245 ~basic_hold_any()
0246 {
0247 table->static_delete(&object);
0248 }
0249
0250
0251 basic_hold_any& assign(basic_hold_any const& x)
0252 {
0253 if (&x != this) {
0254
0255 if (table == x.table) {
0256
0257 table->move(&x.object, &object);
0258 }
0259 else {
0260 reset();
0261 x.table->clone(&x.object, &object);
0262 table = x.table;
0263 }
0264 }
0265 return *this;
0266 }
0267
0268 template <typename T>
0269 basic_hold_any& assign(T const& x)
0270 {
0271
0272 spirit::detail::fxn_ptr_table<Char>* x_table =
0273 spirit::detail::get_table<T>::template get<Char>();
0274 if (table == x_table) {
0275
0276 table->destruct(&object);
0277 if (spirit::detail::get_table<T>::is_small::value) {
0278
0279 new (&object) T(x);
0280 }
0281 else {
0282
0283 new (object) T(x);
0284 }
0285 }
0286 else {
0287 if (spirit::detail::get_table<T>::is_small::value) {
0288
0289 table->destruct(&object);
0290 new (&object) T(x);
0291 }
0292 else {
0293 reset();
0294 object = new T(x);
0295 }
0296 table = x_table;
0297 }
0298 return *this;
0299 }
0300
0301 template <typename T>
0302 static void new_object(void*& object, T const& x, mpl::true_)
0303 {
0304 new (&object) T(x);
0305 }
0306
0307 template <typename T>
0308 static void new_object(void*& object, T const& x, mpl::false_)
0309 {
0310 object = new T(x);
0311 }
0312
0313
0314 #ifdef BOOST_HAS_RVALUE_REFS
0315 template <typename T>
0316 basic_hold_any& operator=(T&& x)
0317 {
0318 return assign(std::forward<T>(x));
0319 }
0320 #else
0321 template <typename T>
0322 basic_hold_any& operator=(T& x)
0323 {
0324 return assign(x);
0325 }
0326
0327 template <typename T>
0328 basic_hold_any& operator=(T const& x)
0329 {
0330 return assign(x);
0331 }
0332 #endif
0333
0334 basic_hold_any& operator=(basic_hold_any const& x)
0335 {
0336 return assign(x);
0337 }
0338
0339
0340 basic_hold_any& swap(basic_hold_any& x)
0341 {
0342 std::swap(table, x.table);
0343 std::swap(object, x.object);
0344 return *this;
0345 }
0346
0347 boost::core::typeinfo const& type() const
0348 {
0349 return table->get_type();
0350 }
0351
0352 template <typename T>
0353 T const& cast() const
0354 {
0355 if (type() != BOOST_CORE_TYPEID(T))
0356 throw bad_any_cast(type(), BOOST_CORE_TYPEID(T));
0357
0358 return spirit::detail::get_table<T>::is_small::value ?
0359 *reinterpret_cast<T const*>(&object) :
0360 *reinterpret_cast<T const*>(object);
0361 }
0362
0363
0364 #ifdef BOOST_SPIRIT_ANY_IMPLICIT_CASTING
0365
0366 template <typename T>
0367 operator T const& () const { return cast<T>(); }
0368 #endif
0369
0370 bool empty() const
0371 {
0372 return table == spirit::detail::get_table<spirit::detail::empty>::template get<Char>();
0373 }
0374
0375 void reset()
0376 {
0377 if (!empty())
0378 {
0379 table->static_delete(&object);
0380 table = spirit::detail::get_table<spirit::detail::empty>::template get<Char>();
0381 object = 0;
0382 }
0383 }
0384
0385
0386
0387
0388
0389 template <typename Char_>
0390 friend inline std::basic_istream<Char_>&
0391 operator>> (std::basic_istream<Char_>& i, basic_hold_any<Char_>& obj)
0392 {
0393 return obj.table->stream_in(i, &obj.object);
0394 }
0395
0396 template <typename Char_>
0397 friend inline std::basic_ostream<Char_>&
0398 operator<< (std::basic_ostream<Char_>& o, basic_hold_any<Char_> const& obj)
0399 {
0400 return obj.table->stream_out(o, &obj.object);
0401 }
0402
0403 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
0404 private:
0405 template <typename T, typename Char_>
0406 friend T* any_cast(basic_hold_any<Char_> *);
0407 #else
0408 public:
0409 #endif
0410
0411 spirit::detail::fxn_ptr_table<Char>* table;
0412 void* object;
0413 };
0414
0415
0416 template <typename T, typename Char>
0417 inline T* any_cast (basic_hold_any<Char>* operand)
0418 {
0419 if (operand && operand->type() == BOOST_CORE_TYPEID(T)) {
0420 return spirit::detail::get_table<T>::is_small::value ?
0421 reinterpret_cast<T*>(&operand->object) :
0422 reinterpret_cast<T*>(operand->object);
0423 }
0424 return 0;
0425 }
0426
0427 template <typename T, typename Char>
0428 inline T const* any_cast(basic_hold_any<Char> const* operand)
0429 {
0430 return any_cast<T>(const_cast<basic_hold_any<Char>*>(operand));
0431 }
0432
0433 template <typename T, typename Char>
0434 T any_cast(basic_hold_any<Char>& operand)
0435 {
0436 typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
0437
0438
0439 nonref* result = any_cast<nonref>(&operand);
0440 if(!result)
0441 boost::throw_exception(bad_any_cast(operand.type(), BOOST_CORE_TYPEID(T)));
0442 return *result;
0443 }
0444
0445 template <typename T, typename Char>
0446 T const& any_cast(basic_hold_any<Char> const& operand)
0447 {
0448 typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;
0449
0450
0451 return any_cast<nonref const&>(const_cast<basic_hold_any<Char> &>(operand));
0452 }
0453
0454
0455
0456 typedef basic_hold_any<char> hold_any;
0457 typedef basic_hold_any<wchar_t> whold_any;
0458
0459 namespace traits
0460 {
0461 template <typename T>
0462 struct is_hold_any : mpl::false_ {};
0463
0464 template <typename Char>
0465 struct is_hold_any<basic_hold_any<Char> > : mpl::true_ {};
0466 }
0467
0468 }}
0469
0470
0471 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
0472 # pragma warning(pop)
0473 #endif
0474
0475 #endif