Bytemaster's Boost Libraries
/Users/dlarimer/dev/libs/dynamic_any/include/boost/dynamic_any.hpp
00001 #ifndef BOOST_DYNAMIC_ANY_INCLUDED
00002 #define BOOST_DYNAMIC_ANY_INCLUDED
00003 
00004 #include <algorithm>
00005 #include <typeinfo>
00006 
00007 #include "boost/config.hpp"
00008 #include <boost/type_traits/remove_reference.hpp>
00009 #include <boost/type_traits/is_reference.hpp>
00010 #include <boost/type_traits/is_scalar.hpp>
00011 #include <boost/throw_exception.hpp>
00012 #include <boost/static_assert.hpp>
00013 
00014 // See boost/python/type_id.hpp
00015 // TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp
00016 # if (defined(__GNUC__) && __GNUC__ >= 3) \
00017  || defined(_AIX) \
00018  || (   defined(__sgi) && defined(__host_mips)) \
00019  || (defined(__hpux) && defined(__HP_aCC)) \
00020  || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
00021 #  define BOOST_AUX_DYNAMIC_ANY_TYPE_ID_NAME
00022 #include <cstring>
00023 # endif 
00024 
00025 namespace boost
00026 {
00027     template<bool IsFundamental, typename ValueType>
00028     struct if_scalar{};
00029 
00030     class dynamic_any
00031     {
00032     public: // structors
00033 
00034         dynamic_any()
00035           : content(0)
00036         {
00037         }
00038 
00039         template<typename ValueType>
00040         dynamic_any(const ValueType & value)
00041           : content(new holder<ValueType, boost::is_scalar<ValueType>::value >(value))
00042         {
00043         }
00044 
00045         dynamic_any(const dynamic_any & other)
00046           : content(other.content ? other.content->clone() : 0)
00047         {
00048         }
00049 
00050         ~dynamic_any()
00051         {
00052             delete content;
00053         }
00054 
00055     public: // modifiers
00056 
00057         dynamic_any & swap(dynamic_any & rhs)
00058         {
00059             std::swap(content, rhs.content);
00060             return *this;
00061         }
00062 
00063         template<typename ValueType>
00064         dynamic_any & operator=(const ValueType & rhs)
00065         {
00066             dynamic_any(rhs).swap(*this);
00067             return *this;
00068         }
00069 
00070         dynamic_any & operator=(dynamic_any rhs)
00071         {
00072             rhs.swap(*this);
00073             return *this;
00074         }
00075 
00076     public: // queries
00077 
00078         bool empty() const
00079         {
00080             return !content;
00081         }
00082 
00083         const std::type_info & type() const
00084         {
00085             return content ? content->type() : typeid(void);
00086         }
00087 
00088 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
00089     private: // types
00090 #else
00091     public: // types (public so dynamic_any_cast can be non-friend)
00092 #endif
00093 
00094         class placeholder
00095         {
00096         public: // structors
00097 
00098             virtual ~placeholder()
00099             {
00100             }
00101 
00102         public: // queries
00103 
00104             virtual const std::type_info & type() const = 0;
00105 
00106             virtual placeholder * clone() const = 0;
00107 
00108         };
00109 
00110         template<typename ValueType, bool IsFundamental>
00111         class holder{};
00112 
00113         template<typename ValueType>
00114         class holder<ValueType,false> : public ValueType, public placeholder
00115         {
00116         public: // structors
00117 
00118             holder(const ValueType & value)
00119               : ValueType(value)
00120             {
00121             }
00122 
00123         public: // queries
00124 
00125             virtual const std::type_info & type() const
00126             {
00127                 return typeid(ValueType);
00128             }
00129 
00130             virtual placeholder * clone() const
00131             {
00132                 return dynamic_cast<placeholder*>(new holder(*this));
00133             }
00134 
00135 
00136         private: // intentionally left unimplemented
00137             holder & operator=(const holder &);
00138         };
00139 
00140         template<typename ValueType>
00141         class holder<ValueType,true> : public placeholder
00142         {
00143         public: // structors
00144 
00145             holder(const ValueType & value)
00146               : held(value)
00147             {
00148             }
00149 
00150         public: // queries
00151 
00152             virtual const std::type_info & type() const
00153             {
00154                 return typeid(ValueType);
00155             }
00156 
00157             virtual placeholder * clone() const
00158             {
00159                 return new holder(held);
00160             }
00161 
00162         public: // representation
00163 
00164             ValueType held;
00165 
00166         private: // intentionally left unimplemented
00167             holder & operator=(const holder &);
00168         };
00169 
00170 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
00171 
00172     private: // representation
00173 
00174         template<typename ValueType>
00175         friend ValueType * dynamic_any_cast(dynamic_any *);
00176 
00177         template<typename ValueType>
00178         friend ValueType * unsafe_any_cast(dynamic_any *);
00179 
00180         template<bool,typename> friend class if_scalar;
00181 #else
00182 
00183     public: // representation (public so dynamic_any_cast can be non-friend)
00184 
00185 #endif
00186 
00187         placeholder * content;
00188 
00189     };
00190 
00191     class bad_dynamic_any_cast : public std::bad_cast
00192     {
00193     public:
00194         virtual const char * what() const throw()
00195         {
00196             return "boost::bad_dynamic_any_cast: "
00197                    "failed conversion using boost::any_cast";
00198         }
00199     };
00200 
00201     template<typename ValueType>
00202     struct if_scalar<false,ValueType>{
00203         static inline ValueType * dynamic_any_cast(dynamic_any * operand)
00204         {
00205             return operand 
00206                 ? dynamic_cast<ValueType*>(operand->content)
00207                 : 0;
00208         }
00209     };
00210     template<typename ValueType>
00211     struct if_scalar<true,ValueType>{
00212         static inline ValueType * dynamic_any_cast(dynamic_any * operand)
00213         {
00214             return operand && 
00215     #ifdef BOOST_AUX_ANY_TYPE_ID_NAME
00216                 std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
00217     #else
00218                 operand->type() == typeid(ValueType)
00219     #endif
00220                 ? &static_cast<dynamic_any::holder<ValueType,true> *>(operand->content)->held
00221                 : 0;
00222         }
00223     };
00224 
00225     template<typename ValueType>
00226     ValueType * dynamic_any_cast(dynamic_any * operand)
00227     {
00228         return  if_scalar<boost::is_scalar<ValueType>::value,ValueType>::dynamic_any_cast(operand);
00229     }
00230 
00231 
00232     template<typename ValueType>
00233     inline const ValueType * dynamic_any_cast(const dynamic_any * operand)
00234     {
00235         return dynamic_any_cast<ValueType>(const_cast<dynamic_any *>(operand));
00236     }
00237 
00238     template<typename ValueType>
00239     ValueType dynamic_any_cast(dynamic_any & operand)
00240     {
00241         typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
00242 
00243 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
00244         // If 'nonref' is still reference type, it means the user has not
00245         // specialized 'remove_reference'.
00246 
00247         // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
00248         // to generate specialization of remove_reference for your class
00249         // See type traits library documentation for details
00250         BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
00251 #endif
00252 
00253         nonref * result = dynamic_any_cast<nonref>(&operand);
00254         if(!result)
00255             boost::throw_exception(bad_dynamic_any_cast());
00256         return *result;
00257     }
00258 
00259     template<typename ValueType>
00260     inline ValueType dynamic_any_cast(const dynamic_any & operand)
00261     {
00262         typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
00263 
00264 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
00265         // The comment in the above version of 'any_cast' explains when this
00266         // assert is fired and what to do.
00267         BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
00268 #endif
00269 
00270         return dynamic_any_cast<const nonref &>(const_cast<dynamic_any &>(operand));
00271     }
00272 
00273     // Note: The "unsafe" versions of dynamic_any_cast are not part of the
00274     // public interface and may be removed at dynamic_any time. They are
00275     // required where we know what type is stored in the dynamic_any and can't
00276     // use typeid() comparison, e.g., when our types may travel across
00277     // different shared libraries.
00278     template<typename ValueType>
00279     inline ValueType * unsafe_any_cast(dynamic_any * operand)
00280     {
00281         return dynamic_any_cast<ValueType>(operand);
00282     }
00283 
00284     template<typename ValueType>
00285     inline const ValueType * unsafe_any_cast(const dynamic_any * operand)
00286     {
00287         return unsafe_any_cast<ValueType>(const_cast<dynamic_any *>(operand));
00288     }
00289 }
00290 
00291 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
00292 //
00293 // Distributed under the Boost Software License, Version 1.0. (See
00294 // accompanying file LICENSE_1_0.txt or copy at
00295 // http://www.boost.org/LICENSE_1_0.txt)
00296 
00297 #endif
 All Classes Namespaces Files Functions Variables Typedefs Defines