00001 #ifndef DVUTIL_ANY_H 00002 #define DVUTIL_ANY_H 00003 // $Id: any.h,v 1.3 2008/11/19 16:56:27 dvermeir Exp $ 00004 00005 #include <typeinfo> 00006 #include <dvutil/basetype.h> 00007 00008 namespace Dv { 00009 /** An Any object can hold any kind of value. This class is 00010 * inspired by boost::any_cast but without the typical 00011 * boost bloat. 00012 */ 00013 class Any { 00014 public: 00015 Any(): it_(0) {} 00016 ~Any() { if (it_) delete it_; } 00017 Any(const Any& a): it_(a.it_ ? a.it_->clone(): 0) {} 00018 00019 /** Constructor. You can stuff an object of any type, except pointer types, 00020 * in an Any object. However, const char* are converted to std::string 00021 * values before storing them. 00022 * @param t value of a non-pointer type, or of type const char* 00023 */ 00024 template<typename T> 00025 Any(const T& t): it_(new Object<T>(t)) {} 00026 00027 /** Constructor for const char* objects. 00028 * @param s value to store in an Any object. 00029 */ 00030 Any(const char* s): it_( s ? new Object<std::string>(s) : 0) {} 00031 00032 /** Return type of value in Any object. This almost only be used 00033 * for comparing with another @a typeid(T). 00034 * @return type info on value in this object 00035 */ 00036 const std::type_info& type() const { return (it_ ? it_->type() : typeid(void) ); } 00037 /** Does this object contain a value? 00038 * @return true iff this object does not contain a value. 00039 */ 00040 bool null() const { return it_ == 0; } 00041 00042 /** Convert an Any object to its underlying value type. 00043 * @param any pointer to an Any object to convert to type T 00044 * @return pointer to underlying T-value or 0 if none (including if type mismatch) 00045 */ 00046 template<typename U> 00047 friend U* any_cast(const Any* any) { 00048 return ((any && any->type() == typeid(U)) ? &static_cast<Any::Object<U>*>(any->it_)->t_ :0); 00049 } 00050 00051 private: 00052 00053 /** Forbid Any values containing pointers. Use e.g. vectors. 00054 * Except const char*, see above. 00055 */ 00056 template<typename T> 00057 Any(const T*); 00058 00059 struct AbstractObject { 00060 virtual ~AbstractObject() {} 00061 virtual const std::type_info & type() const = 0; 00062 virtual AbstractObject* clone() const = 0; 00063 }; 00064 00065 template<typename T> 00066 struct Object: public AbstractObject { 00067 Object(const T& t): t_(t) {} 00068 const std::type_info& type() const { return typeid(T); } 00069 AbstractObject* clone() const { return new Object(t_); } 00070 T t_; 00071 }; 00072 00073 00074 AbstractObject* it_; 00075 }; 00076 00077 /** Convert an Any object to its underlying value type. 00078 * @param any object to convert to type T 00079 * @return T-value of Any object 00080 */ 00081 template<typename T> 00082 T any_cast(const Any& any) { 00083 typedef typename basetype<T>::base base_t; 00084 const base_t* result = any_cast<base_t>(&any); 00085 if (! result) 00086 throw std::domain_error("Dv::any_cast error"); 00087 return *result; 00088 }; 00089 00090 } 00091 #endif
dvutil-1.0.10 | [ 5 December, 2009] |