00001 00007 #ifndef ___POLYMORPH_H___ 00008 #define ___POLYMORPH_H___ 00009 00010 #include <cstring> 00011 #include <string> 00012 using std::string; 00013 #include <typeinfo> 00014 #include <cassert> 00015 00016 #include "../src/stringutils.h" 00017 #include "../src/stringparser.h" 00018 #include "../src/allocatingpointer.h" 00019 #include "../src/tristate.h" 00020 #include "../src/typeless.h" 00021 00022 00023 #ifdef ANSI_COMPATIBLE 00024 /* Optional: defines LONG_DOUBLE_UNAVAILABLE where needed */ 00025 #include "../src/ind_types.h" 00026 #endif 00027 00028 00029 00030 /* Forward declaration */ 00031 template <class T> class Polymorph; 00032 00033 00039 template <class T> 00040 class PolymorphBase : public Typeless { 00041 public: 00042 typedef T value_type; 00043 typedef PolymorphBase<value_type> self; 00044 virtual ~PolymorphBase() { } 00045 00046 PolymorphBase(const value_type val) : p(val) { }; 00047 PolymorphBase( value_type* ptr) : p(ptr) { }; 00048 00049 virtual bool operator< (const Typeless& o) const; 00050 virtual bool operator> (const Typeless& o) const; 00051 00052 bool operator< (const self& o) const { return (*p < *(o.p)); } 00053 bool operator> (const self& o) const { return (*p > *(o.p)); } 00054 00055 bool operator< (const value_type& o) const { return (*p < o ); } 00056 bool operator> (const value_type& o) const { return (*p > o ); } 00057 00058 self& operator= (const value_type& o) { p=o; return *this; } 00059 Typeless& set(const Typeless& o); 00060 00061 const value_type& operator* () const { return *p; } 00062 00065 value_type* valueptr() const { return p.valueptr(); } 00066 00067 virtual string stringrep(String::StreamFormat format=String::StreamFormat()) const 00068 { return String::stringrep(*p,format); } 00069 00070 virtual string typestring() const 00071 { return (name_str? string(name_str) : string(typeid(T).name())); } 00072 00079 static void set_typestring(const char* str) { name_str=str; } 00080 00087 virtual Typeless* parse(const StringParser& parser, const string& s) const { 00088 value_type result; 00089 (void)parser; (void)s; 00090 parser.parse(s,result); 00091 return new Polymorph<value_type>(result); 00092 } 00093 00098 virtual Typeless* clone() const { return new self(*this); }; 00099 00100 virtual Typeless* duplicate() const { return new self(*p); }; 00101 00102 protected: 00103 AllocatingPointer<value_type> p; 00104 00105 static const char* name_str; 00106 }; 00107 00108 00109 00110 /* Static variables */ 00111 template <class T> 00112 const char* PolymorphBase<T>::name_str=0; 00113 00114 00115 00117 template <class T> 00118 bool PolymorphBase<T>::operator< (const Typeless& o) const 00119 { 00120 /* First try to match exact type */ 00121 const self* oself = dynamic_cast<const self*>(&o); 00122 if (oself) return (*this < **oself); 00123 00124 /* Fall back to numeric comparison if both are numbers */ 00125 if (isnumeric() && o.isnumeric()) 00126 return (numericvalue() < o.numericvalue()); 00127 00128 assert(0); /* Unsupported comparison */ 00129 exit(-1); 00130 return true; 00131 } 00132 00133 00134 00136 template <class T> 00137 bool PolymorphBase<T>::operator> (const Typeless& o) const 00138 { 00139 /* First try to match exact type */ 00140 const self* oself = dynamic_cast<const self*>(&o); 00141 if (oself) return (*this > **oself); 00142 00143 /* Fall back to numeric comparison if both are numbers */ 00144 if (isnumeric() && o.isnumeric()) 00145 return (numericvalue() > o.numericvalue()); 00146 00147 assert(0); /* Unsupported comparison */ 00148 exit(-1); 00149 return true; 00150 } 00151 00152 00153 00161 template <class T> 00162 Typeless& PolymorphBase<T>::set(const Typeless& o) 00163 { 00164 const self* oself = dynamic_cast<const self*>(&o); 00165 if (oself) p = *(oself->p); 00166 else { assert(0); } // Unsupported assignment; should be an exception instead 00167 00168 return *this; 00169 } 00170 00171 00172 00175 template <class T> 00176 class Polymorph : public PolymorphBase<T> { 00177 public: 00178 typedef T value_type; 00179 typedef Polymorph<value_type> self; 00180 virtual ~Polymorph() { } 00181 Polymorph(const value_type val) : PolymorphBase<value_type>(val) { }; 00182 Polymorph( value_type* ptr) : PolymorphBase<value_type>(ptr) { }; 00183 virtual Typeless* clone() const { return new self(*this); }; 00184 virtual Typeless* duplicate() const { return new self(*p); }; 00185 }; 00186 00187 00192 template <class T> 00193 Polymorph<T> make_Polymorph(T* ptr) 00194 { return Polymorph<T>(ptr); } 00195 00196 00197 00200 template <class T> 00201 Polymorph<T> allocating_Polymorph(const T& val) 00202 { return Polymorph<T>(val); } 00203 00204 00223 #define NumericPolymorph(type)\ 00224 template <> class Polymorph<type> : public PolymorphBase<type> {\ 00225 public:\ 00226 typedef type value_type;\ 00227 typedef Polymorph<value_type> self;\ 00228 virtual ~Polymorph() { }\ 00229 Polymorph(value_type val) : PolymorphBase<value_type>(val) { };\ 00230 Polymorph(value_type* ptr) : PolymorphBase<value_type>(ptr) { };\ 00231 virtual Typeless* clone() const { return new self(*this); };\ 00232 virtual Typeless* duplicate() const { return new self(*p); };\ 00233 virtual bool isnumeric() const { return true; }\ 00234 virtual Typeless::exprtype numericvalue() const\ 00235 { return Typeless::exprtype(*p); }\ 00236 virtual string prettyprint(String::StreamFormat format=String::StreamFormat()) const\ 00237 { return (*p==Uninitialized ? std::string("Uninitialized") : stringrep(format)); }\ 00238 } 00239 00240 NumericPolymorph(int); 00241 NumericPolymorph(double); 00242 NumericPolymorph(Tristate); 00243 00244 00245 00247 template <> class Polymorph<string> : public PolymorphBase<string> { 00248 public: 00249 typedef string value_type; 00250 typedef Polymorph<value_type> self; 00251 virtual ~Polymorph() { } 00252 Polymorph(value_type val) : PolymorphBase<value_type>(val) { }; 00253 Polymorph(value_type* ptr) : PolymorphBase<value_type>(ptr) { }; 00254 virtual Typeless* clone() const { return new self(*this); }; 00255 virtual Typeless* duplicate() const { return new self(*p); }; 00256 virtual string prettyprint(String::StreamFormat format=String::StreamFormat()) const\ 00257 { return ("\"" + stringrep(format) + "\""); } 00258 }; 00259 00260 00261 #endif /* ___POLYMORPH_H___ */