Bytemaster's Boost Libraries
|
00001 #ifndef _BOOST_ANY_REF_HPP_ 00002 #define _BOOST_ANY_REF_HPP_ 00003 #include <typeinfo> 00004 #include <new> 00005 #include <string.h> 00006 #include <boost/throw_exception.hpp> 00007 00008 namespace boost { 00009 00010 namespace detail { 00011 namespace any_ref { 00012 struct place_holder { 00013 virtual ~place_holder(){} 00014 virtual const std::type_info & type() const { 00015 return typeid(place_holder); 00016 } 00017 }; 00018 00019 template<typename T> 00020 struct place_holder_impl : private place_holder { 00021 }; 00022 00023 template<typename T> 00024 struct place_holder_impl<const T&> : public place_holder { 00025 place_holder_impl( const T& v ):m_ref(v){} 00026 virtual const std::type_info & type() const { 00027 return typeid(const T&); 00028 } 00029 const T& m_ref; 00030 }; 00031 00032 template<typename T> 00033 struct place_holder_impl<T&> : public place_holder_impl<const T&> { 00034 place_holder_impl( T& v ) 00035 :place_holder_impl<const T&>(v){} 00036 00037 virtual const std::type_info & type() const { 00038 return typeid(T&); 00039 } 00040 }; 00041 } // namespace any_ref 00042 } // namespace detail 00043 00044 class bad_any_ref_cast : public std::bad_cast 00045 { 00046 public: 00047 virtual const char * what() const throw() { 00048 return "boost::bad_any_ref_cast: " 00049 "failed conversion using boost::any_ref"; 00050 } 00051 }; 00052 00060 class any_ref 00061 { 00062 public: 00063 any_ref() { 00064 new (held) detail::any_ref::place_holder(); 00065 } 00066 00067 template<typename T> 00068 any_ref( const T& v ) { 00069 new (held) detail::any_ref::place_holder_impl<const T&>(v); 00070 } 00071 00072 template<typename T> 00073 any_ref( T& v ) { 00074 new (held) detail::any_ref::place_holder_impl<T&>(v); 00075 } 00076 00077 const std::type_info& type()const { return ((detail::any_ref::place_holder*)held)->type(); } 00078 00079 template<typename T> 00080 inline operator const T&()const { 00081 const T* v = const_ptr<T>(); 00082 if( !v ) 00083 boost::throw_exception(bad_any_ref_cast()); 00084 return *v; 00085 } 00086 template<typename T> 00087 inline const T* const_ptr()const { 00088 detail::any_ref::place_holder_impl<const T&>* p = 00089 dynamic_cast<detail::any_ref::place_holder_impl<const T&>* >((detail::any_ref::place_holder*)held); 00090 if( p ) 00091 return &p->m_ref; 00092 return 0; 00093 } 00094 00095 template<typename T> 00096 inline operator T&()const { 00097 T* v = ptr<T>(); 00098 if( !v ) 00099 boost::throw_exception(bad_any_ref_cast()); 00100 return *v; 00101 } 00102 template<typename T> 00103 inline T* ptr()const { 00104 detail::any_ref::place_holder_impl<T&>* p = 00105 dynamic_cast<detail::any_ref::place_holder_impl<T&>* >((detail::any_ref::place_holder*)held); 00106 if( p ) 00107 return const_cast<T*>(&p->m_ref); 00108 return 0; 00109 } 00110 00111 any_ref& operator=( const any_ref& r ) { 00112 if( this != &r ) 00113 memcpy(held,r.held,sizeof(held)); 00114 return *this; 00115 } 00116 template<typename T> 00117 any_ref& operator=( const T& v ) { 00118 new (held) detail::any_ref::place_holder_impl<const T&>(v); 00119 return *this; 00120 } 00121 template<typename T> 00122 any_ref& operator=( T& v ) { 00123 new (held) detail::any_ref::place_holder_impl<T&>(v); 00124 return *this; 00125 } 00126 00127 private: 00128 00129 char held[sizeof(detail::any_ref::place_holder_impl<const int&>)]; 00130 }; 00131 00132 } // namespace boost 00133 00134 #endif