⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hold_any.hpp

📁 Boost provides free peer-reviewed portable C++ source libraries. We emphasize libraries that work
💻 HPP
字号:
//  Copyright (c) 2008 Hartmut Kaiser//  Copyright (c) Christopher Diggins 2005//  Copyright (c) Pablo Aguilar 2005//  Copyright (c) Kevlin Henney 2001////  Distributed under the Boost Software License, Version 1.0. (See accompanying//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)////  The class boost::spirit::hold_any is built based on the any class//  published here: http://www.codeproject.com/cpp/dynamic_typing.asp. It adds//  support for std streaming operator<<() and operator>>().#if !defined(BOOST_SPIRIT_HOLD_ANY_MAY_02_2007_0857AM)#define BOOST_SPIRIT_HOLD_ANY_MAY_02_2007_0857AM#include <boost/config.hpp>#include <boost/type_traits/remove_reference.hpp>#include <boost/type_traits/is_reference.hpp>#include <boost/throw_exception.hpp>#include <boost/static_assert.hpp>#include <boost/mpl/bool.hpp>#include <boost/assert.hpp>#include <stdexcept>#include <typeinfo>#include <algorithm>#include <iosfwd>///////////////////////////////////////////////////////////////////////////////#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)  # pragma warning(push)  # pragma warning(disable: 4100)   // 'x': unreferenced formal parameter  # pragma warning(disable: 4127)   // conditional expression is constant#endif ///////////////////////////////////////////////////////////////////////////////namespace boost { namespace spirit{    struct bad_any_cast      : std::bad_cast    {        bad_any_cast(std::type_info const& src, std::type_info const& dest)          : from(src.name()), to(dest.name())        {}        virtual const char* what() const throw() { return "bad any cast"; }        const char* from;        const char* to;    };    namespace detail    {        // function pointer table        struct fxn_ptr_table        {            std::type_info const& (*get_type)();            void (*static_delete)(void**);            void (*destruct)(void**);            void (*clone)(void* const*, void**);            void (*move)(void* const*, void**);            std::istream& (*stream_in)(std::istream&, void**);            std::ostream& (*stream_out)(std::ostream&, void* const*);        };        // static functions for small value-types        template<typename Small>        struct fxns;        template<>        struct fxns<mpl::true_>        {            template<typename T>            struct type            {                static std::type_info const& get_type()                {                    return typeid(T);                }                static void static_delete(void** x)                {                    reinterpret_cast<T*>(x)->~T();                }                static void destruct(void** x)                {                    reinterpret_cast<T*>(x)->~T();                }                static void clone(void* const* src, void** dest)                {                    new (dest) T(*reinterpret_cast<T const*>(src));                }                static void move(void* const* src, void** dest)                {                    reinterpret_cast<T*>(dest)->~T();                    *reinterpret_cast<T*>(dest) =                        *reinterpret_cast<T const*>(src);                }                static std::istream& stream_in (std::istream& i, void** obj)                {                    i >> *reinterpret_cast<T*>(obj);                    return i;                }                static std::ostream& stream_out(std::ostream& o, void* const* obj)                {                    o << *reinterpret_cast<T const*>(obj);                    return o;                }            };        };        // static functions for big value-types (bigger than a void*)        template<>        struct fxns<mpl::false_>        {            template<typename T>            struct type            {                static std::type_info const& get_type()                {                    return typeid(T);                }                static void static_delete(void** x)                {                    // destruct and free memory                    delete (*reinterpret_cast<T**>(x));                }                static void destruct(void** x)                {                    // destruct only, we'll reuse memory                    (*reinterpret_cast<T**>(x))->~T();                }                static void clone(void* const* src, void** dest)                {                    *dest = new T(**reinterpret_cast<T* const*>(src));                }                static void move(void* const* src, void** dest)                {                    (*reinterpret_cast<T**>(dest))->~T();                    **reinterpret_cast<T**>(dest) =                        **reinterpret_cast<T* const*>(src);                }                static std::istream& stream_in(std::istream& i, void** obj)                {                    i >> **reinterpret_cast<T**>(obj);                    return i;                }                static std::ostream& stream_out(std::ostream& o, void* const* obj)                {                    o << **reinterpret_cast<T* const*>(obj);                    return o;                }            };        };        template<typename T>        struct get_table        {            typedef mpl::bool_<(sizeof(T) <= sizeof(void*))> is_small;            static fxn_ptr_table* get()            {                static fxn_ptr_table static_table =                {                    fxns<is_small>::template type<T>::get_type,                    fxns<is_small>::template type<T>::static_delete,                    fxns<is_small>::template type<T>::destruct,                    fxns<is_small>::template type<T>::clone,                    fxns<is_small>::template type<T>::move,                    fxns<is_small>::template type<T>::stream_in,                    fxns<is_small>::template type<T>::stream_out                };                return &static_table;            }        };        ///////////////////////////////////////////////////////////////////////        struct empty {};        inline std::istream&        operator>> (std::istream& i, empty&)        {            // If this assertion fires you tried to insert from a std istream            // into an empty hold_any instance. This simply can't work, because            // there is no way to figure out what type to extract from the            // stream.            // The only way to make this work is to assign an arbitrary            // value of the required type to the hold_any instance you want to            // stream to. This assignment has to be executed before the actual            // call to the operator>>().            BOOST_ASSERT(false);            return i;        }        inline std::ostream&        operator<< (std::ostream& o, empty const&)        {            return o;        }    }    ///////////////////////////////////////////////////////////////////////////    class hold_any    {    public:        // constructors        template <typename T>        hold_any(T const& x)          : table(spirit::detail::get_table<T>::get()), object(0)        {            if (spirit::detail::get_table<T>::is_small::value)                new (&object) T(x);            else                object = new T(x);        }        hold_any()          : table(spirit::detail::get_table<spirit::detail::empty>::get()),            object(0)        {        }        hold_any(hold_any const& x)          : table(spirit::detail::get_table<spirit::detail::empty>::get()),            object(0)        {            assign(x);        }        ~hold_any()        {            table->static_delete(&object);        }        // assignment        hold_any& assign(hold_any const& x)        {            if (&x != this) {                // are we copying between the same type?                if (table == x.table) {                    // if so, we can avoid reallocation                    table->move(&x.object, &object);                }                else {                    reset();                    x.table->clone(&x.object, &object);                    table = x.table;                }            }            return *this;        }        template <typename T>        hold_any& assign(T const& x)        {            // are we copying between the same type?            spirit::detail::fxn_ptr_table* x_table =                 spirit::detail::get_table<T>::get();            if (table == x_table) {            // if so, we can avoid deallocating and re-use memory                table->destruct(&object);    // first destruct the old content                if (spirit::detail::get_table<T>::is_small::value) {                    // create copy on-top of object pointer itself                    new (&object) T(x);                }                else {                    // create copy on-top of old version                    new (object) T(x);                }            }            else {                if (spirit::detail::get_table<T>::is_small::value) {                    // create copy on-top of object pointer itself                    table->destruct(&object); // first destruct the old content                    new (&object) T(x);                 }                else {                    reset();                  // first delete the old content                    object = new T(x);                }                table = x_table;      // update table pointer            }            return *this;        }        // assignment operator        template <typename T>        hold_any& operator=(T const& x)        {            return assign(x);        }        // utility functions        hold_any& swap(hold_any& x)        {            std::swap(table, x.table);            std::swap(object, x.object);            return *this;        }        std::type_info const& type() const        {            return table->get_type();        }        template <typename T>        T const& cast() const        {            if (type() != typeid(T))              throw bad_any_cast(type(), typeid(T));            return spirit::detail::get_table<T>::is_small::value ?                *reinterpret_cast<T const*>(&object) :                *reinterpret_cast<T const*>(object);        }// implicit casting is disabled by default for compatibility with boost::any#ifdef BOOST_SPIRIT_ANY_IMPLICIT_CASTING        // automatic casting operator        template <typename T>        operator T const& () const { return cast<T>(); }#endif // implicit casting        bool empty() const        {            return table == spirit::detail::get_table<spirit::detail::empty>::get();        }        void reset()        {            if (!empty())            {                table->static_delete(&object);                table = spirit::detail::get_table<spirit::detail::empty>::get();                object = 0;            }        }    // these functions have been added in the assumption that the embedded    // type has a corresponding operator defined, which is completely safe    // because spirit::hold_any is used only in contexts where these operators    // do exist        friend std::istream& operator>> (std::istream& i, hold_any& obj)        {            return obj.table->stream_in(i, &obj.object);        }        friend std::ostream& operator<< (std::ostream& o, hold_any const& obj)        {            return obj.table->stream_out(o, &obj.object);        }#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS    private: // types        template<typename T>        friend T* any_cast(hold_any *);#else    public: // types (public so any_cast can be non-friend)#endif        // fields        spirit::detail::fxn_ptr_table* table;        void* object;    };    // boost::any-like casting    template <typename T>    inline T* any_cast (hold_any* operand)    {        if (operand && operand->type() == typeid(T)) {            return spirit::detail::get_table<T>::is_small::value ?                reinterpret_cast<T*>(&operand->object) :                reinterpret_cast<T*>(operand->object);        }        return 0;    }    template <typename T>    inline T const* any_cast(hold_any const* operand)    {        return any_cast<T>(const_cast<hold_any*>(operand));    }    template <typename T>    T any_cast(hold_any& operand)    {        typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION        // If 'nonref' is still reference type, it means the user has not        // specialized 'remove_reference'.        // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro        // to generate specialization of remove_reference for your class        // See type traits library documentation for details        BOOST_STATIC_ASSERT(!is_reference<nonref>::value);#endif        nonref* result = any_cast<nonref>(&operand);        if(!result)            boost::throw_exception(bad_any_cast(operand.type(), typeid(T)));        return *result;    }    template <typename T>    T const& any_cast(hold_any const& operand)    {        typedef BOOST_DEDUCED_TYPENAME remove_reference<T>::type nonref;#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION        // The comment in the above version of 'any_cast' explains when this        // assert is fired and what to do.        BOOST_STATIC_ASSERT(!is_reference<nonref>::value);#endif        return any_cast<nonref const&>(const_cast<hold_any &>(operand));    }///////////////////////////////////////////////////////////////////////////////}}    // namespace boost::spirit///////////////////////////////////////////////////////////////////////////////#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)  # pragma warning(pop)  #endif #endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -