Teuchos_any.hpp
Go to the documentation of this file.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 const std::string ValueTypeName = TypeNameTraits<ValueType>::name();
00225 TEST_FOR_EXCEPTION(
00226 operand.type() != typeid(ValueType), bad_any_cast
00227 ,"any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
00228 << "any::holder<"<<ValueTypeName<<"> failed since the actual underlying type is \'"
00229 << typeName(*operand.access_content()) << "!"
00230 );
00231 TEST_FOR_EXCEPTION(
00232 !operand.access_content(), bad_any_cast
00233 ,"any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
00234 << "any::holder<"<<ValueTypeName<<"> failed because the content is NULL"
00235 );
00236 any::holder<ValueType>
00237 *dyn_cast_content = dynamic_cast<any::holder<ValueType>*>(operand.access_content());
00238 TEST_FOR_EXCEPTION(
00239 !dyn_cast_content, std::logic_error
00240 ,"any_cast<"<<ValueTypeName <<">(operand): Error, cast to type "
00241 << "any::holder<"<<ValueTypeName<<"> failed but should not have and the actual underlying type is \'"
00242 << typeName(*operand.access_content()) << "!"
00243 << " The problem might be related to incompatible RTTI systems in static and shared libraries!"
00244 );
00245 return dyn_cast_content->held;
00246 }
00247
00257 template<typename ValueType>
00258 const ValueType& any_cast(const any &operand)
00259 {
00260 return any_cast<ValueType>(const_cast<any&>(operand));
00261 }
00262
00266 inline std::string toString(const any &rhs)
00267 {
00268 std::ostringstream oss;
00269 rhs.print(oss);
00270 return oss.str();
00271 }
00272
00276 inline bool operator==( const any &a, const any &b )
00277 {
00278 return a.same(b);
00279 }
00280
00284 inline bool operator!=( const any &a, const any &b )
00285 {
00286 return !a.same(b);
00287 }
00288
00292 inline std::ostream & operator<<(std::ostream & os, const any &rhs)
00293 {
00294 rhs.print(os);
00295 return os;
00296 }
00297
00298 }
00299
00300 #endif // TEUCHOS_ANY_HPP