00001 /* ======================================================================== 00002 ** Extended Template and Library 00003 ** Abstraction for a Generic Value Type 00004 ** $Id: _value.h 659 2007-09-12 21:01:33Z dooglus $ 00005 ** 00006 ** Copyright (c) 2002 Adrian Bentley 00007 ** 00008 ** This package is free software; you can redistribute it and/or 00009 ** modify it under the terms of the GNU General Public License as 00010 ** published by the Free Software Foundation; either version 2 of 00011 ** the License, or (at your option) any later version. 00012 ** 00013 ** This package is distributed in the hope that it will be useful, 00014 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 ** General Public License for more details. 00017 ** 00018 ** === N O T E S =========================================================== 00019 ** 00020 ** This is an internal header file, included by other ETL headers. 00021 ** You should not attempt to use it directly. 00022 ** 00023 ** ========================================================================= */ 00024 00025 /* === S T A R T =========================================================== */ 00026 00027 #ifndef __ETL_VALUE_H 00028 #define __ETL_VALUE_H 00029 00030 /* === H E A D E R S ======================================================= */ 00031 #include <algorithm> 00032 #include <typeinfo> 00033 #include <cassert> 00034 00035 /* === M A C R O S ========================================================= */ 00036 00037 /* === T Y P E D E F S ===================================================== */ 00038 00039 /* === C L A S S E S & S T R U C T S ======================================= */ 00040 00050 template < typename T > 00051 class value_store_type 00052 { 00053 public: 00054 typedef T value_type; 00055 }; 00056 00057 _ETL_BEGIN_NAMESPACE 00058 00065 class value 00066 { 00067 struct contentholder 00068 { 00069 virtual ~contentholder() {} 00070 virtual contentholder *clone() const = 0; 00071 virtual const std::type_info &type() const = 0; 00072 }; 00073 00074 contentholder *content; 00075 00076 public: //constructor interface 00077 value() 00078 :content(0) 00079 { 00080 } 00081 00082 value(const value &v) 00083 :content( v.content ? v.content->clone() : 0 ) 00084 { 00085 } 00086 00087 /* Copies the object passed to it 00088 */ 00089 template < typename T > 00090 value(const T &v) 00091 :content( new holder< typename value_store_type<T>::value_type > 00092 (reinterpret_cast<const typename value_store_type<T>::value_type &>(v)) ) 00093 { 00094 } 00095 00096 public: //modifier interface 00097 00098 value & swap(value & rhs) 00099 { 00100 std::swap(content, rhs.content); 00101 return *this; 00102 } 00103 00104 template<typename ValueType> 00105 value & operator=(const ValueType & rhs) 00106 { 00107 value(rhs).swap(*this); 00108 return *this; 00109 } 00110 00111 value & operator=(const value & rhs) 00112 { 00113 value(rhs).swap(*this); 00114 return *this; 00115 } 00116 00117 public: //query interface 00118 00119 bool empty() const 00120 { 00121 return content == 0; 00122 } 00123 00124 const std::type_info & type() const 00125 { 00126 return content ? content->type() : typeid(void); 00127 } 00128 00129 private: //implementation interface 00130 00131 template < typename T > 00132 class holder : public contentholder 00133 { 00134 public: //representation 00135 T obj; 00136 00137 public: //constructor interface 00138 00139 holder(const T &o) 00140 :obj(o) 00141 { 00142 } 00143 00144 holder(const holder<T> &h) 00145 :obj(h.obj) 00146 { 00147 } 00148 00149 public: //accessor interface 00150 virtual contentholder *clone() const 00151 { 00152 return new holder(*this); 00153 } 00154 00155 virtual const std::type_info &type() const 00156 { 00157 return typeid(T); 00158 } 00159 00160 public: //allocation interface 00161 void *operator new(unsigned int size) 00162 { 00163 assert(size == sizeof(holder<T>)); 00164 00165 //use pool allocation at some point 00166 return malloc(size); 00167 } 00168 00169 void operator delete(void *p) 00170 { 00171 assert(p); 00172 //use pool allocation at some point 00173 return free(p); 00174 } 00175 }; 00176 00177 template < typename ValueType > 00178 friend ValueType *value_cast(value *v); 00179 }; 00180 00183 class bad_value_cast : public std::bad_cast 00184 { 00185 public: 00186 virtual const char * what() const throw() 00187 { 00188 return "etl::bad_value_cast: " "failed conversion using boost::value_cast"; 00189 } 00190 }; 00191 00198 template < typename ValueType > 00199 ValueType *value_cast(value *v) 00200 { 00201 assert(v); 00202 00203 return ( typeid(typename value_store_type<ValueType>::value_type) == v->type() ) 00204 ? &static_cast<value::holder<ValueType> *>(v->content)->obj 00205 : 0; 00206 } 00207 00211 template < typename ValueType > 00212 const ValueType * value_cast(const value *v) 00213 { 00214 return value_cast<ValueType>(const_cast<value *>(v)); 00215 } 00216 00224 template < typename ValueType > 00225 ValueType value_cast(const value &v) 00226 { 00227 const ValueType * result = value_cast<ValueType>(&v); 00228 if(!result) 00229 throw bad_value_cast(); 00230 return *result; 00231 } 00232 00233 _ETL_END_NAMESPACE 00234 00235 /* === E N D =============================================================== */ 00236 00237 #endif