--- /usr/include/boost/any.hpp 2009-02-26 05:16:09.000000000 -0700 +++ any.hpp 2009-04-07 21:53:43.630130210 -0700 @@ -12,38 +12,135 @@ #include #include +#include #include "boost/config.hpp" -#include -#include +#include #include #include +#include +#include namespace boost { + + namespace detail + { + namespace any + { + + template struct fn_table_impl + { + template struct t + { + + static inline const void * clone(const void * in) + { + return new T(*(static_cast(in))); + } + + static inline const void * clone(const T& in) + { + return new T(in); + } + + static inline T * get(const void * in) + { + return const_cast(static_cast(in)); + } + + static inline void release(const void * in) + { + delete const_cast(static_cast(in)); + } + + }; + + }; + + template <> struct fn_table_impl + { + template struct t { + static inline const void * clone(const void * in) + { + return reinterpret_cast(T(reinterpret_cast(in))); + } + + static inline const void * clone(const T& in) + { + return reinterpret_cast(T(in)); + } + + static inline T * get(const void * in) + { + return const_cast(reinterpret_cast(&in)); + } + + static inline void release(const void *) {}; // Will fall out of scope + }; + }; + + template struct fn_table { + + typedef fn_table_impl::value> type; + + static inline const void * clone(const void * in) + { + return type::template t::clone(in); + } + + static inline const void * clone(const ValueType& in) + { + return type::template t::clone(in); + } + + static inline ValueType * get(const void * in) + { + return type::template t::get(in); + } + + static inline void release(const void * in) + { + type::template t::release(in); + } + + static inline const void * clone(const shared_ptr& in) + { + return type::template t::clone(in.get()); + } + + static inline ValueType * get(const shared_ptr& in) + { + return type::template t::get(in.get()); + } + + }; + + } + } + class any { public: // structors - any() - : content(0) + any() : type_info(typeid(void)) { } template any(const ValueType & value) - : content(new holder(value)) + : content(detail::any::fn_table::clone(value), &(detail::any::fn_table::release)), + type_info(typeid(ValueType)) { } any(const any & other) - : content(other.content ? other.content->clone() : 0) + : content(other.content), type_info(other.type_info) { } ~any() { - delete content; } public: // modifiers @@ -76,60 +173,10 @@ const std::type_info & type() const { - return content ? content->type() : typeid(void); + return type_info; } #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS - private: // types -#else - public: // types (public so any_cast can be non-friend) -#endif - - class placeholder - { - public: // structors - - virtual ~placeholder() - { - } - - public: // queries - - virtual const std::type_info & type() const = 0; - - virtual placeholder * clone() const = 0; - - }; - - template - class holder : public placeholder - { - public: // structors - - holder(const ValueType & value) - : held(value) - { - } - - public: // queries - - virtual const std::type_info & type() const - { - return typeid(ValueType); - } - - virtual placeholder * clone() const - { - return new holder(held); - } - - public: // representation - - ValueType held; - - }; - -#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS private: // representation @@ -137,6 +184,9 @@ friend ValueType * any_cast(any *); template + friend const ValueType& any_cast(any &); + + template friend ValueType * unsafe_any_cast(any *); #else @@ -145,8 +195,8 @@ #endif - placeholder * content; - + shared_ptr content; + const std::type_info& type_info; }; class bad_any_cast : public std::bad_cast @@ -162,9 +212,10 @@ template ValueType * any_cast(any * operand) { - return operand && operand->type() == typeid(ValueType) - ? &static_cast *>(operand->content)->held - : 0; + if (operand->type() != typeid(ValueType)) return; + if (operand->content.use_count() != 1) + operand->content.reset(detail::any::fn_table::clone(operand->content)); + return detail::any::fn_table::get(operand->content); } template @@ -173,42 +224,18 @@ return any_cast(const_cast(operand)); } - template - ValueType any_cast(const any & operand) + template + const ValueType& any_cast(any & operand) { - typedef BOOST_DEDUCED_TYPENAME remove_reference::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::value); -#endif - - const nonref * result = any_cast(&operand); - if(!result) + if (operand.type() != typeid(ValueType)) boost::throw_exception(bad_any_cast()); - return *result; + return *(detail::any::fn_table::get(operand.content)); } template - ValueType any_cast(any & operand) + const ValueType& any_cast(const any & operand) { - typedef BOOST_DEDUCED_TYPENAME remove_reference::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::value); -#endif - - nonref * result = any_cast(&operand); - if(!result) - boost::throw_exception(bad_any_cast()); - return *result; + return any_cast(const_cast(operand)); } // Note: The "unsafe" versions of any_cast are not part of the @@ -219,7 +246,9 @@ template inline ValueType * unsafe_any_cast(any * operand) { - return &static_cast *>(operand->content)->held; + if (operand->content.use_count() != 1) + operand->content.reset(detail::any::fn_table::clone(operand->content)); + return detail::any::fn_table::get(operand->content); } template