Bytemaster's Boost Libraries
|
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