--- /usr/include/boost/any.hpp 2009-02-26 05:16:09.000000000 -0700 +++ /home/michael/Scripts/c++/sharing_any/any.hpp 2009-04-05 20:32:05.947904690 -0700 @@ -18,6 +18,7 @@ #include #include #include +#include namespace boost { @@ -34,16 +35,18 @@ any(const ValueType & value) : content(new holder(value)) { + content->add_ref(); } any(const any & other) - : content(other.content ? other.content->clone() : 0) + : content(other.content) { + if (content) content->add_ref(); } ~any() { - delete content; + if (content) content->rem_ref(); } public: // modifiers @@ -89,6 +92,11 @@ { public: // structors + placeholder() + : references(0) + { + } + virtual ~placeholder() { } @@ -99,6 +107,20 @@ virtual placeholder * clone() const = 0; + public: // reference counting + + detail::atomic_count references; + + void add_ref() + { + ++references; + } + + void rem_ref() + { + if (--references == 0) delete this; + } + }; template @@ -137,8 +159,26 @@ friend ValueType * any_cast(any *); template + friend ValueType any_cast(any &); + + template + friend ValueType any_cast(const any &); + + template friend ValueType * unsafe_any_cast(any *); + private: // reference counting + + void make_unique() const + { + if (content && content->references != 1) { + any* unconst = const_cast(this); + unconst->content->rem_ref(); + unconst->content = unconst->content->clone(); + unconst->content->add_ref(); + } + } + #else public: // representation (public so any_cast can be non-friend) @@ -162,6 +202,7 @@ template ValueType * any_cast(any * operand) { + operand->make_unique(); return operand && operand->type() == typeid(ValueType) ? &static_cast *>(operand->content)->held : 0; @@ -176,39 +217,17 @@ template ValueType any_cast(const 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) - boost::throw_exception(bad_any_cast()); - return *result; + if (operand.type() == typeid(ValueType)) + return static_cast *>(operand.content)->held; + boost::throw_exception(bad_any_cast()); } template ValueType any_cast(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; + if (operand.type() == typeid(ValueType)) + return static_cast *>(operand.content)->held; + boost::throw_exception(bad_any_cast()); } // Note: The "unsafe" versions of any_cast are not part of the @@ -219,6 +238,7 @@ template inline ValueType * unsafe_any_cast(any * operand) { + operand->make_unique(); return &static_cast *>(operand->content)->held; }