Marsyas  0.5.0-beta1
/Users/jleben/code/marsyas/src/marsyas/realtime/any.h
Go to the documentation of this file.
00001 // A clone of boost::any for Marsyas.
00002 // Author: Jakob Leben <jakob.leben@gmail.com>
00003 
00004 // See http://www.boost.org/libs/any for Documentation.
00005 
00006 #ifndef MARSYAS_REALTIME_ANY_INCLUDED
00007 #define MARSYAS_REALTIME_ANY_INCLUDED
00008 
00009 // what:  variant type boost::any
00010 // who:   contributed by Kevlin Henney,
00011 //        with features contributed and bugs found by
00012 //        Ed Brey, Mark Rodgers, Peter Dimov, and James Curran
00013 // when:  July 2001
00014 // where: tested with BCC 5.5, MSVC 6.0, and g++ 2.95
00015 
00016 #include <algorithm>
00017 #include <typeinfo>
00018 
00019 //#include "boost/config.hpp"
00020 //#include <boost/type_traits/remove_reference.hpp>
00021 //#include <boost/type_traits/is_reference.hpp>
00022 //#include <boost/throw_exception.hpp>
00023 //#include <boost/static_assert.hpp>
00024 
00025 // See boost/python/type_id.hpp
00026 // TODO: add BOOST_TYPEID_COMPARE_BY_NAME to config.hpp
00027 # if (defined(__GNUC__) && __GNUC__ >= 3) \
00028  || defined(_AIX) \
00029  || (   defined(__sgi) && defined(__host_mips)) \
00030  || (defined(__hpux) && defined(__HP_aCC)) \
00031  || (defined(linux) && defined(__INTEL_COMPILER) && defined(__ICC))
00032 #  define BOOST_AUX_ANY_TYPE_ID_NAME
00033 #include <cstring>
00034 # endif
00035 
00036 namespace Marsyas {
00037 namespace RealTime
00038 {
00039 class any
00040 {
00041 public: // structors
00042 
00043   any()
00044     : content(0)
00045   {
00046   }
00047 
00048   template<typename ValueType>
00049   any(const ValueType & value)
00050     : content(new holder<ValueType>(value))
00051   {
00052   }
00053 
00054   any(const any & other)
00055     : content(other.content ? other.content->clone() : 0)
00056   {
00057   }
00058 
00059   ~any()
00060   {
00061     delete content;
00062   }
00063 
00064 public: // modifiers
00065 
00066   any & swap(any & rhs)
00067   {
00068     std::swap(content, rhs.content);
00069     return *this;
00070   }
00071 
00072   template<typename ValueType>
00073   any & operator=(const ValueType & rhs)
00074   {
00075     any(rhs).swap(*this);
00076     return *this;
00077   }
00078 
00079   any & operator=(any rhs)
00080   {
00081     rhs.swap(*this);
00082     return *this;
00083   }
00084 
00085 public: // queries
00086 
00087   bool empty() const
00088   {
00089     return !content;
00090   }
00091 
00092   const std::type_info & type() const
00093   {
00094     return content ? content->type() : typeid(void);
00095   }
00096 
00097 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
00098 private: // types
00099 #else
00100 public: // types (public so any_cast can be non-friend)
00101 #endif
00102 
00103   class placeholder
00104   {
00105   public: // structors
00106 
00107     virtual ~placeholder()
00108     {
00109     }
00110 
00111   public: // queries
00112 
00113     virtual const std::type_info & type() const = 0;
00114 
00115     virtual placeholder * clone() const = 0;
00116 
00117   };
00118 
00119   template<typename ValueType>
00120   class holder : public placeholder
00121   {
00122   public: // structors
00123 
00124     holder(const ValueType & value)
00125       : held(value)
00126     {
00127     }
00128 
00129   public: // queries
00130 
00131     virtual const std::type_info & type() const
00132     {
00133       return typeid(ValueType);
00134     }
00135 
00136     virtual placeholder * clone() const
00137     {
00138       return new holder(held);
00139     }
00140 
00141   public: // representation
00142 
00143     ValueType held;
00144 
00145   private: // intentionally left unimplemented
00146     holder & operator=(const holder &);
00147   };
00148 
00149 #ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS
00150 
00151 private: // representation
00152 
00153   template<typename ValueType>
00154   friend ValueType * any_cast(any *);
00155 
00156   template<typename ValueType>
00157   friend ValueType * unsafe_any_cast(any *);
00158 
00159 #else
00160 
00161 public: // representation (public so any_cast can be non-friend)
00162 
00163 #endif
00164 
00165   placeholder * content;
00166 
00167 };
00168 
00169 class bad_any_cast : public std::bad_cast
00170 {
00171 public:
00172   virtual const char * what() const throw()
00173   {
00174     return "boost::bad_any_cast: "
00175            "failed conversion using boost::any_cast";
00176   }
00177 };
00178 
00179 template<typename ValueType>
00180 ValueType * any_cast(any * operand)
00181 {
00182   return operand &&
00183 #ifdef BOOST_AUX_ANY_TYPE_ID_NAME
00184          std::strcmp(operand->type().name(), typeid(ValueType).name()) == 0
00185 #else
00186          operand->type() == typeid(ValueType)
00187 #endif
00188          ? &static_cast<any::holder<ValueType> *>(operand->content)->held
00189          : 0;
00190 }
00191 
00192 template<typename ValueType>
00193 inline const ValueType * any_cast(const any * operand)
00194 {
00195   return any_cast<ValueType>(const_cast<any *>(operand));
00196 }
00197 
00198 template<typename ValueType>
00199 ValueType any_cast(any & operand)
00200 {
00201 #if NOT_MARSYAS
00202   typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
00203 
00204 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
00205   // If 'nonref' is still reference type, it means the user has not
00206   // specialized 'remove_reference'.
00207 
00208   // Please use BOOST_BROKEN_COMPILER_TYPE_TRAITS_SPECIALIZATION macro
00209   // to generate specialization of remove_reference for your class
00210   // See type traits library documentation for details
00211   BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
00212 #endif
00213 
00214   nonref * result = any_cast<nonref>(&operand);
00215 #else
00216   ValueType * result = any_cast<ValueType>(&operand);
00217 #endif
00218   if(!result)
00219     throw bad_any_cast();
00220   return *result;
00221 }
00222 
00223 template<typename ValueType>
00224 inline ValueType any_cast(const any & operand)
00225 {
00226 #if NOT_MARSYAS
00227   typedef BOOST_DEDUCED_TYPENAME remove_reference<ValueType>::type nonref;
00228 
00229 #ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
00230   // The comment in the above version of 'any_cast' explains when this
00231   // assert is fired and what to do.
00232   BOOST_STATIC_ASSERT(!is_reference<nonref>::value);
00233 #endif
00234 
00235   return any_cast<const nonref &>(const_cast<any &>(operand));
00236 #else
00237   return any_cast<ValueType>(const_cast<any &>(operand));
00238 #endif
00239 }
00240 
00241 // Note: The "unsafe" versions of any_cast are not part of the
00242 // public interface and may be removed at any time. They are
00243 // required where we know what type is stored in the any and can't
00244 // use typeid() comparison, e.g., when our types may travel across
00245 // different shared libraries.
00246 template<typename ValueType>
00247 inline ValueType * unsafe_any_cast(any * operand)
00248 {
00249   return &static_cast<any::holder<ValueType> *>(operand->content)->held;
00250 }
00251 
00252 template<typename ValueType>
00253 inline const ValueType * unsafe_any_cast(const any * operand)
00254 {
00255   return unsafe_any_cast<ValueType>(const_cast<any *>(operand));
00256 }
00257 }
00258 }
00259 
00260 // Copyright Kevlin Henney, 2000, 2001, 2002. All rights reserved.
00261 //
00262 // Distributed under the Boost Software License, Version 1.0. (See
00263 // accompanying file LICENSE_1_0.txt or copy at
00264 // http://www.boost.org/LICENSE_1_0.txt)
00265 
00266 #endif