00001 #ifndef TEUCHOS_ANY_HPP
00002 #define TEUCHOS_ANY_HPP
00003
00008 #include "Teuchos_TestForException.hpp"
00009 #include "Teuchos_TypeNameTraits.hpp"
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 namespace Teuchos {
00039
00043 class any
00044 {
00045 public:
00047 any()
00048 : content(0)
00049 {}
00050
00052 template<typename ValueType>
00053 explicit any(const ValueType & value)
00054 : content(new holder<ValueType>(value))
00055 {}
00056
00058 any(const any & other)
00059 : content(other.content ? other.content->clone() : 0)
00060 {}
00061
00063 ~any()
00064 {
00065 delete content;
00066 }
00067
00069 any & swap(any & rhs)
00070 {
00071 std::swap(content, rhs.content);
00072 return *this;
00073 }
00074
00076 template<typename ValueType>
00077 any & operator=(const ValueType & rhs)
00078 {
00079 any(rhs).swap(*this);
00080 return *this;
00081 }
00082
00084 any & operator=(const any & rhs)
00085 {
00086 any(rhs).swap(*this);
00087 return *this;
00088 }
00089
00091 bool empty() const
00092 {
00093 return !content;
00094 }
00095
00097 const std::type_info & type() const
00098 {
00099 return content ? content->type() : typeid(void);
00100 }
00101
00103 std::string typeName() const
00104 {
00105 return content ? content->typeName() : "NONE";
00106 }
00107
00109 bool same( const any &other ) const
00110 {
00111 if( this->empty() && other.empty() )
00112 return true;
00113 else if( this->empty() && !other.empty() )
00114 return false;
00115 else if( !this->empty() && other.empty() )
00116 return false;
00117
00118 return content->same(*other.content);
00119 }
00120
00122 void print(std::ostream& os) const
00123 {
00124 if (content) content->print(os);
00125 }
00126
00127 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00128
00130
00132 class placeholder
00133 {
00134 public:
00136 virtual ~placeholder() {}
00138 virtual const std::type_info & type() const = 0;
00140 virtual std::string typeName() const = 0;
00142 virtual placeholder * clone() const = 0;
00144 virtual bool same( const placeholder &other ) const = 0;
00146 virtual void print(std::ostream & os) const = 0;
00147 };
00148
00150 template<typename ValueType>
00151 class holder : public placeholder
00152 {
00153 public:
00155 holder(const ValueType & value)
00156 : held(value)
00157 {}
00159 const std::type_info & type() const
00160 { return typeid(ValueType); }
00162 std::string typeName() const
00163 { return TypeNameTraits<ValueType>::name(); }
00165 placeholder * clone() const
00166 { return new holder(held); }
00168 bool same( const placeholder &other ) const
00169 {
00170 if( type() != other.type() ) {
00171 return false;
00172 }
00173
00174 const ValueType
00175 &other_held = dynamic_cast<const holder<ValueType>&>(other).held;
00176 return held == other_held;
00177 }
00179 void print(std::ostream & os) const
00180 { os << held; }
00182 ValueType held;
00183 };
00184
00186
00187 public:
00188
00189 placeholder* access_content()
00190 { return content; }
00191 const placeholder* access_content() const
00192 { return content; }
00193 #endif
00194
00195 private:
00196
00197
00198
00199
00200 placeholder * content;
00201
00202 };
00203
00207 class bad_any_cast : public std::runtime_error
00208 {
00209 public:
00210 bad_any_cast( const std::string msg ) : std::runtime_error(msg) {}
00211 };
00212
00221 template<typename ValueType>
00222 ValueType& any_cast(any &operand)
00223 {
00224
00225 const std::string ValueTypeName = TypeNameTraits<ValueType>::name();
00226 bool type_mismatch = ( operand.type() != typeid(ValueType) );
00227 #ifdef HAVE_SHARED
00228
00229
00230
00231 if ( type_mismatch )
00232 type_mismatch = ( strcmp(operand.type().name(), typeid(ValueType).name()) != 0 );
00233 #endif
00234 TEST_FOR_EXCEPTION(
00235 type_mismatch, bad_any_cast
00236 ,"any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
00237 << "any::holder<"<<ValueTypeName<<"> failed since the actual underlying type is \'"
00238 << typeName(*operand.access_content()) << "!"
00239 );
00240
00241 TEST_FOR_EXCEPTION(
00242 !operand.access_content(), bad_any_cast
00243 ,"any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
00244 << "any::holder<"<<ValueTypeName<<"> failed because the content is NULL"
00245 );
00246
00247
00248
00249
00250
00251 any::holder<ValueType>
00252 *dyn_cast_content = dynamic_cast<any::holder<ValueType>*>(operand.access_content());
00253 #ifdef HAVE_SHARED
00254
00255
00256
00257 if ( !dyn_cast_content )
00258 dyn_cast_content = static_cast<any::holder<ValueType>*>(operand.access_content());
00259
00260
00261
00262
00263
00264
00265
00266
00267 #endif
00268 TEST_FOR_EXCEPTION(
00269 !dyn_cast_content, std::logic_error
00270 ,"any_cast<"<<ValueTypeName <<">(operand): Error, cast to type "
00271 << "any::holder<"<<ValueTypeName<<"> failed but should not have and the actual underlying type is \'"
00272 << typeName(*operand.access_content()) << "!"
00273 );
00274
00275 return dyn_cast_content->held;
00276
00277 }
00278
00288 template<typename ValueType>
00289 const ValueType& any_cast(const any &operand)
00290 {
00291 return any_cast<ValueType>(const_cast<any&>(operand));
00292 }
00293
00297 inline std::string toString(const any &rhs)
00298 {
00299 std::ostringstream oss;
00300 rhs.print(oss);
00301 return oss.str();
00302 }
00303
00307 inline bool operator==( const any &a, const any &b )
00308 {
00309 return a.same(b);
00310 }
00311
00315 inline bool operator!=( const any &a, const any &b )
00316 {
00317 return !a.same(b);
00318 }
00319
00323 inline std::ostream & operator<<(std::ostream & os, const any &rhs)
00324 {
00325 rhs.print(os);
00326 return os;
00327 }
00328
00329 }
00330
00331 #endif // TEUCHOS_ANY_HPP