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 // This file was taken from the boost library which contained the
00013 // following notice:
00014 //
00015 // *************************************************************
00016 //
00017 // what:  variant type boost::any
00018 // who:   contributed by Kevlin Henney,
00019 //        with features contributed and bugs found by
00020 //        Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
00021 // when:  July 2001
00022 // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
00023 //
00024 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
00025 //
00026 // Permission to use, copy, modify, and distribute this software for any
00027 // purpose is hereby granted without fee, provided that this copyright and
00028 // permissions notice appear in all copies and derivatives.
00029 //
00030 // This software is provided "as is" without express or implied warranty.
00031 //
00032 // *************************************************************
00033 //
00034 // RAB modified the file for use in Teuchos.  I changed the nature of
00035 // the any_cast<> to be easier to use.
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       // !this->empty() && !other.empty()
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         // type() == other.type()
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   // Danger: This is made public to allow any_cast to be non-friend
00189   placeholder* access_content()
00190     { return content; }
00191   const placeholder* access_content() const
00192     { return content; }
00193 #endif
00194 
00195 private:
00196 
00197   // /////////////////////////
00198   // Private data members
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     << typeid(*operand.access_content()).name() << "!"
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     << typeid(*operand.access_content()).name() << "!"
00243     );
00244   return dyn_cast_content->held;
00245 }
00246 
00256 template<typename ValueType>
00257 const ValueType& any_cast(const any &operand)
00258 {
00259   return any_cast<ValueType>(const_cast<any&>(operand));
00260 }
00261 
00265 inline std::string toString(const any &rhs)
00266 {
00267   std::ostringstream oss;
00268   rhs.print(oss);
00269   return oss.str();
00270 }
00271 
00275 inline bool operator==( const any &a, const any &b )
00276 {
00277   return a.same(b);
00278 }
00279 
00283 inline bool operator!=( const any &a, const any &b )
00284 {
00285   return !a.same(b);
00286 }
00287 
00291 inline std::ostream & operator<<(std::ostream & os, const any &rhs)
00292 {
00293   rhs.print(os);
00294   return os;
00295 }
00296 
00297 } // namespace Teuchos
00298 
00299 #endif // TEUCHOS_ANY_HPP

Generated on Thu Sep 18 12:30:29 2008 for Teuchos - Trilinos Tools Package by doxygen 1.3.9.1