Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Teuchos_any.hpp
Go to the documentation of this file.
00001 /*
00002 // @HEADER
00003 // ***********************************************************************
00004 //
00005 //                    Teuchos: Common Tools Package
00006 //                 Copyright (2004) Sandia Corporation
00007 //
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 //
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA
00025 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00026 //
00027 // ***********************************************************************
00028 // @HEADER
00029 */
00030 
00031 #ifndef TEUCHOS_ANY_HPP
00032 #define TEUCHOS_ANY_HPP
00033 
00038 #include "Teuchos_TestForException.hpp"
00039 #include "Teuchos_TypeNameTraits.hpp"
00040 
00041 //
00042 // This file was taken from the boost library which contained the
00043 // following notice:
00044 //
00045 // *************************************************************
00046 //
00047 // what:  variant type boost::any
00048 // who:   contributed by Kevlin Henney,
00049 //        with features contributed and bugs found by
00050 //        Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
00051 // when:  July 2001
00052 // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
00053 //
00054 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
00055 //
00056 // Permission to use, copy, modify, and distribute this software for any
00057 // purpose is hereby granted without fee, provided that this copyright and
00058 // permissions notice appear in all copies and derivatives.
00059 //
00060 // This software is provided "as is" without express or implied warranty.
00061 //
00062 // *************************************************************
00063 //
00064 // RAB modified the file for use in Teuchos.  I changed the nature of
00065 // the any_cast<> to be easier to use.
00066 //
00067 
00068 namespace Teuchos {
00069 
00073 class TEUCHOS_LIB_DLL_EXPORT any
00074 {
00075 public:
00077   any()
00078     : content(0)
00079     {}
00080 
00082   template<typename ValueType>
00083   explicit any(const ValueType & value)
00084     : content(new holder<ValueType>(value))
00085     {}
00086   
00088   any(const any & other)
00089     : content(other.content ? other.content->clone() : 0)
00090     {}
00091 
00093   ~any()
00094     {
00095       delete content;
00096     }
00097 
00099   any & swap(any & rhs)
00100     {
00101       std::swap(content, rhs.content);
00102       return *this;
00103     }
00104   
00106   template<typename ValueType>
00107   any & operator=(const ValueType & rhs)
00108     {
00109       any(rhs).swap(*this);
00110       return *this;
00111     }
00112   
00114   any & operator=(const any & rhs)
00115     {
00116       any(rhs).swap(*this);
00117       return *this;
00118     }
00119   
00121   bool empty() const
00122     {
00123       return !content;
00124     }
00125   
00127   const std::type_info & type() const
00128     {
00129       return content ? content->type() : typeid(void);
00130     }
00131   
00133   std::string typeName() const
00134     {
00135       return content ? content->typeName() : "NONE";
00136     }
00137   
00139   bool same( const any &other ) const
00140     {
00141       if( this->empty() && other.empty() )
00142         return true;
00143       else if( this->empty() && !other.empty() )
00144         return false;
00145       else if( !this->empty() && other.empty() )
00146         return false;
00147       // !this->empty() && !other.empty()
00148       return content->same(*other.content);
00149     }
00150 
00152   void print(std::ostream& os) const
00153     {
00154       if (content) content->print(os);
00155     }
00156 
00157 #ifndef DOXYGEN_SHOULD_SKIP_THIS
00158 
00160 
00162   class placeholder
00163   {
00164   public:
00166     virtual ~placeholder() {}
00168     virtual const std::type_info & type() const = 0;
00170     virtual std::string typeName() const = 0;
00172     virtual placeholder * clone() const = 0;
00174     virtual bool same( const placeholder &other ) const = 0;
00176     virtual void print(std::ostream & os) const = 0;
00177   };
00178   
00180   template<typename ValueType>
00181   class holder : public placeholder
00182   {
00183   public:
00185     holder(const ValueType & value)
00186       : held(value)
00187       {}
00189     const std::type_info & type() const
00190       { return typeid(ValueType); }
00192     std::string typeName() const
00193       { return TypeNameTraits<ValueType>::name(); }
00195     placeholder * clone() const
00196       { return new holder(held); }
00198     bool same( const placeholder &other ) const
00199       {
00200         if( type() != other.type() ) {
00201           return false;
00202         }
00203         // type() == other.type()
00204         const ValueType
00205           &other_held = dynamic_cast<const holder<ValueType>&>(other).held;
00206         return held == other_held;
00207       }
00209     void print(std::ostream & os) const
00210       { os << held; }
00212     ValueType held;
00213   };
00214 
00216 
00217 public:
00218   // Danger: This is made public to allow any_cast to be non-friend
00219   placeholder* access_content()
00220     { return content; }
00221   const placeholder* access_content() const
00222     { return content; }
00223 #endif
00224 
00225 private:
00226 
00227   // /////////////////////////
00228   // Private data members
00229   
00230   placeholder * content;
00231 
00232 };
00233 
00237 class bad_any_cast : public std::runtime_error
00238 {
00239 public:
00240   bad_any_cast( const std::string msg ) : std::runtime_error(msg) {}
00241 };
00242 
00251 template<typename ValueType>
00252 ValueType& any_cast(any &operand)
00253 {
00254   const std::string ValueTypeName = TypeNameTraits<ValueType>::name();
00255   TEST_FOR_EXCEPTION(
00256     operand.type() != typeid(ValueType), bad_any_cast
00257     ,"any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
00258     << "any::holder<"<<ValueTypeName<<"> failed since the actual underlying type is \'"
00259     << typeName(*operand.access_content()) << "!"
00260     );
00261   TEST_FOR_EXCEPTION(
00262     !operand.access_content(), bad_any_cast
00263     ,"any_cast<"<<ValueTypeName<<">(operand): Error, cast to type "
00264     << "any::holder<"<<ValueTypeName<<"> failed because the content is NULL"
00265     );
00266   any::holder<ValueType>
00267     *dyn_cast_content = dynamic_cast<any::holder<ValueType>*>(operand.access_content());
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     << "  The problem might be related to incompatible RTTI systems in static and shared libraries!"
00274     );
00275   return dyn_cast_content->held;
00276 }
00277 
00287 template<typename ValueType>
00288 const ValueType& any_cast(const any &operand)
00289 {
00290   return any_cast<ValueType>(const_cast<any&>(operand));
00291 }
00292 
00296 inline std::string toString(const any &rhs)
00297 {
00298   std::ostringstream oss;
00299   rhs.print(oss);
00300   return oss.str();
00301 }
00302 
00306 inline bool operator==( const any &a, const any &b )
00307 {
00308   return a.same(b);
00309 }
00310 
00314 inline bool operator!=( const any &a, const any &b )
00315 {
00316   return !a.same(b);
00317 }
00318 
00322 inline std::ostream & operator<<(std::ostream & os, const any &rhs)
00323 {
00324   rhs.print(os);
00325   return os;
00326 }
00327 
00328 } // namespace Teuchos
00329 
00330 #endif // TEUCHOS_ANY_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines