1 /* ========================================================================
2 ** Extended Template and Library
3 ** Abstraction for a Generic Value Type
6 ** Copyright (c) 2002 Adrian Bentley
8 ** This package is free software; you can redistribute it and/or
9 ** modify it under the terms of the GNU General Public License as
10 ** published by the Free Software Foundation; either version 2 of
11 ** the License, or (at your option) any later version.
13 ** This package is distributed in the hope that it will be useful,
14 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 ** General Public License for more details.
18 ** === N O T E S ===========================================================
20 ** This is an internal header file, included by other ETL headers.
21 ** You should not attempt to use it directly.
23 ** ========================================================================= */
25 /* === S T A R T =========================================================== */
27 #ifndef __ETL__VALUE_H
28 #define __ETL__VALUE_H
30 /* === H E A D E R S ======================================================= */
35 /* === M A C R O S ========================================================= */
37 /* === T Y P E D E F S ===================================================== */
39 /* === C L A S S E S & S T R U C T S ======================================= */
41 /*! \note This class may be specialized to support binary compatibility
42 for desired objects (e.g. point3,vector3,float[3]).
43 However it MUST be declared within scope that you are using the
46 \warning If you specialize this class for something that isn't binary
47 compatible, then your values could easily report belonging to
50 template < typename T >
51 class value_store_type
59 /*! \class value _value.h ETL/value
60 \brief Abstraction of the concept of a generic value
62 Modified from ideas for the boost::any type. Added binary compatibility
69 virtual ~contentholder() {}
70 virtual contentholder *clone() const = 0;
71 virtual const std::type_info &type() const = 0;
74 contentholder *content;
76 public: //constructor interface
83 :content( v.content ? v.content->clone() : 0 )
87 /* Copies the object passed to it
89 template < typename T >
91 :content( new holder< typename value_store_type<T>::value_type >
92 (reinterpret_cast<const typename value_store_type<T>::value_type &>(v)) )
96 public: //modifier interface
98 value & swap(value & rhs)
100 std::swap(content, rhs.content);
104 template<typename ValueType>
105 value & operator=(const ValueType & rhs)
107 value(rhs).swap(*this);
111 value & operator=(const value & rhs)
113 value(rhs).swap(*this);
117 public: //query interface
124 const std::type_info & type() const
126 return content ? content->type() : typeid(void);
129 private: //implementation interface
131 template < typename T >
132 class holder : public contentholder
134 public: //representation
137 public: //constructor interface
144 holder(const holder<T> &h)
149 public: //accessor interface
150 virtual contentholder *clone() const
152 return new holder(*this);
155 virtual const std::type_info &type() const
160 public: //allocation interface
161 void *operator new(unsigned int size)
163 assert(size == sizeof(holder<T>));
165 //use pool allocation at some point
169 void operator delete(void *p)
172 //use pool allocation at some point
177 template < typename ValueType >
178 friend ValueType *value_cast(value *v);
181 /*! Is thrown for bad value_casts (when using a reference...)
183 class bad_value_cast : public std::bad_cast
186 virtual const char * what() const throw()
188 return "etl::bad_value_cast: " "failed conversion using boost::value_cast";
192 /*! Returns a pointer to the desired value type if the value_type and the internal
193 binary format agree (mediated by using the value_store_type class), otherwise
196 \see value_store_type
198 template < typename ValueType >
199 ValueType *value_cast(value *v)
203 return ( typeid(typename value_store_type<ValueType>::value_type) == v->type() )
204 ? &static_cast<value::holder<ValueType> *>(v->content)->obj
208 /*! Same as above except tweaked to allow const cast (possibly for purposes involving
209 type agreement... if const impacts a typeid call I do not know...)
211 template < typename ValueType >
212 const ValueType * value_cast(const value *v)
214 return value_cast<ValueType>(const_cast<value *>(v));
217 /*! Extract a copy of the internal object and will throw a bad_value_cast exception
218 if the types do not agree.
220 \note I'm not sure why boost::any didn't use a reference here... there must be a reason...
224 template < typename ValueType >
225 ValueType value_cast(const value &v)
227 const ValueType * result = value_cast<ValueType>(&v);
229 throw bad_value_cast();
235 /* === E N D =============================================================== */