File indexing completed on 2025-10-30 08:35:35
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