williamr@2: // See http://www.boost.org/libs/any for Documentation. williamr@2: williamr@2: #ifndef BOOST_ANY_INCLUDED williamr@2: #define BOOST_ANY_INCLUDED williamr@2: williamr@2: // what: variant type boost::any williamr@2: // who: contributed by Kevlin Henney, williamr@2: // with features contributed and bugs found by williamr@2: // Ed Brey, Mark Rodgers, Peter Dimov, and James Curran williamr@2: // when: July 2001 williamr@2: // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95 williamr@2: williamr@2: #include williamr@2: #include williamr@2: williamr@2: #include "boost/config.hpp" williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: #include williamr@2: williamr@2: namespace boost williamr@2: { williamr@2: class any williamr@2: { williamr@2: public: // structors williamr@2: williamr@2: any() williamr@2: : content(0) williamr@2: { williamr@2: } williamr@2: williamr@2: template williamr@2: any(const ValueType & value) williamr@2: : content(new holder(value)) williamr@2: { williamr@2: } williamr@2: williamr@2: any(const any & other) williamr@2: : content(other.content ? other.content->clone() : 0) williamr@2: { williamr@2: } williamr@2: williamr@2: ~any() williamr@2: { williamr@2: delete content; williamr@2: } williamr@2: williamr@2: public: // modifiers williamr@2: williamr@2: any & swap(any & rhs) williamr@2: { williamr@2: std::swap(content, rhs.content); williamr@2: return *this; williamr@2: } williamr@2: williamr@2: template williamr@2: any & operator=(const ValueType & rhs) williamr@2: { williamr@2: any(rhs).swap(*this); williamr@2: return *this; williamr@2: } williamr@2: williamr@2: any & operator=(const any & rhs) williamr@2: { williamr@2: any(rhs).swap(*this); williamr@2: return *this; williamr@2: } williamr@2: williamr@2: public: // queries williamr@2: williamr@2: bool empty() const williamr@2: { williamr@2: return !content; williamr@2: } williamr@2: williamr@2: const std::type_info & type() const williamr@2: { williamr@2: return content ? content->type() : typeid(void); williamr@2: } williamr@2: williamr@2: #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS williamr@2: private: // types williamr@2: #else williamr@2: public: // types (public so any_cast can be non-friend) williamr@2: #endif williamr@2: williamr@2: class placeholder williamr@2: { williamr@2: public: // structors williamr@2: williamr@2: virtual ~placeholder() williamr@2: { williamr@2: } williamr@2: williamr@2: public: // queries williamr@2: williamr@2: virtual const std::type_info & type() const = 0; williamr@2: williamr@2: virtual placeholder * clone() const = 0; williamr@2: williamr@2: }; williamr@2: williamr@2: template williamr@2: class holder : public placeholder williamr@2: { williamr@2: public: // structors williamr@2: williamr@2: holder(const ValueType & value) williamr@2: : held(value) williamr@2: { williamr@2: } williamr@2: williamr@2: public: // queries williamr@2: williamr@2: virtual const std::type_info & type() const williamr@2: { williamr@2: return typeid(ValueType); williamr@2: } williamr@2: williamr@2: virtual placeholder * clone() const williamr@2: { williamr@2: return new holder(held); williamr@2: } williamr@2: williamr@2: public: // representation williamr@2: williamr@2: ValueType held; williamr@2: williamr@2: }; williamr@2: williamr@2: #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS williamr@2: williamr@2: private: // representation williamr@2: williamr@2: template williamr@2: friend ValueType * any_cast(any *); williamr@2: williamr@2: template williamr@2: friend ValueType * unsafe_any_cast(any *); williamr@2: williamr@2: #else williamr@2: williamr@2: public: // representation (public so any_cast can be non-friend) williamr@2: williamr@2: #endif williamr@2: williamr@2: placeholder * content; williamr@2: williamr@2: }; williamr@2: williamr@2: class bad_any_cast : public std::bad_cast williamr@2: { williamr@2: public: williamr@2: virtual const char * what() const throw() williamr@2: { williamr@2: return "boost::bad_any_cast: " williamr@2: "failed conversion using boost::any_cast"; williamr@2: } williamr@2: }; williamr@2: williamr@2: template williamr@2: ValueType * any_cast(any * operand) williamr@2: { williamr@2: return operand && operand->type() == typeid(ValueType) williamr@2: ? &static_cast *>(operand->content)->held williamr@2: : 0; williamr@2: } williamr@2: williamr@2: template williamr@2: const ValueType * any_cast(const any * operand) williamr@2: { williamr@2: return any_cast(const_cast(operand)); williamr@2: } williamr@2: williamr@2: template williamr@2: ValueType any_cast(const any & operand) williamr@2: { williamr@2: typedef BOOST_DEDUCED_TYPENAME remove_reference::type nonref; williamr@2: williamr@2: #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION williamr@2: // If 'nonref' is still reference type, it means the user has not williamr@2: // specialized 'remove_reference'. williamr@2: williamr@2: // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro williamr@2: // to generate specialization of remove_reference for your class williamr@2: // See type traits library documentation for details williamr@2: BOOST_STATIC_ASSERT(!is_reference::value); williamr@2: #endif williamr@2: williamr@2: const nonref * result = any_cast(&operand); williamr@2: if(!result) williamr@2: boost::throw_exception(bad_any_cast()); williamr@2: return *result; williamr@2: } williamr@2: williamr@2: template williamr@2: ValueType any_cast(any & operand) williamr@2: { williamr@2: typedef BOOST_DEDUCED_TYPENAME remove_reference::type nonref; williamr@2: williamr@2: #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION williamr@2: // The comment in the above version of 'any_cast' explains when this williamr@2: // assert is fired and what to do. williamr@2: BOOST_STATIC_ASSERT(!is_reference::value); williamr@2: #endif williamr@2: williamr@2: nonref * result = any_cast(&operand); williamr@2: if(!result) williamr@2: boost::throw_exception(bad_any_cast()); williamr@2: return *result; williamr@2: } williamr@2: williamr@2: // Note: The "unsafe" versions of any_cast are not part of the williamr@2: // public interface and may be removed at any time. They are williamr@2: // required where we know what type is stored in the any and can't williamr@2: // use typeid() comparison, e.g., when our types may travel across williamr@2: // different shared libraries. williamr@2: template williamr@2: inline ValueType * unsafe_any_cast(any * operand) williamr@2: { williamr@2: return &static_cast *>(operand->content)->held; williamr@2: } williamr@2: williamr@2: template williamr@2: inline const ValueType * unsafe_any_cast(const any * operand) williamr@2: { williamr@2: return unsafe_any_cast(const_cast(operand)); williamr@2: } williamr@2: } williamr@2: williamr@2: // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved. williamr@2: // williamr@2: // Distributed under the Boost Software License, Version 1.0. (See williamr@2: // accompanying file LICENSE_1_0.txt or copy at williamr@2: // http://www.boost.org/LICENSE_1_0.txt) williamr@2: williamr@2: #endif