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