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 
00225   const std::string ValueTypeName = TypeNameTraits<ValueType>::name();
00226   bool type_mismatch = ( operand.type() != typeid(ValueType) );
00227 #ifdef HAVE_SHARED
00228   // For shared libraries, the above may resolve as true because one
00229   // of the types is not fully qualified.  The following check will
00230   // compensate for that.
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   // 2007/11/28: rabartl: Note: If we get here, then the rest of this function
00248   // should succeed and should be a formality.  The dynamic cast is the safe
00249   // thing to do and therefore we try that.  However, this may actually fail
00250   // with shared libraries with g++ (see below).
00251   any::holder<ValueType>
00252     *dyn_cast_content = dynamic_cast<any::holder<ValueType>*>(operand.access_content());
00253 #ifdef HAVE_SHARED
00254   // For shared libraries, dynamic_cast does not work across shared
00255   // library boundaries, so we use static_cast, which will prevent any
00256   // runtime errors at the expense of being more dangerous.
00257   if ( !dyn_cast_content )
00258     dyn_cast_content = static_cast<any::holder<ValueType>*>(operand.access_content());
00259   // 2007/11/28: rabartl: Above, this static cast is not safe for some
00260   // possible types but that should be very rare.  Note that if a program
00261   // performing the dynamic casts works correctly with a static library
00262   // (i.e. HAVE_SHARED is not defined), and if the compiler can figure out the
00263   // static case correctly, then this should be safe for the shared library
00264   // case.  We really need to look into issues of RTTI and shared libraries
00265   // and see what the C++ standard says about this and if there are any g++
00266   // command-line options for fixing this ...
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 } // namespace Teuchos
00330 
00331 #endif // TEUCHOS_ANY_HPP

Generated on Tue Oct 20 12:45:25 2009 for Teuchos - Trilinos Tools Package by doxygen 1.4.7