Guest User

Untitled

a guest
May 21st, 2012
27
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.40 KB | None | 0 0
  1. Flexibly convert between string, int, double for C Variant Class
  2. Variant a = 7;
  3. cout << "The answer is" + a.ToString() << endl; // should print "The answer is 7"
  4. a = "7.4";
  5. double &b = a.ToDouble();
  6. b += 1;
  7. cout << a.ToString() << endl; // should print 8.4
  8.  
  9. #include <string>
  10. #include <iostream>
  11. class Variant{
  12. public:
  13. Variant(){
  14. data.type = UNKOWN;
  15. data.intVal = 0;
  16. }
  17. Variant(int v){
  18. data.type = INT;
  19. data.intVal = v;
  20. }
  21. Variant(double v){
  22. data.type = DOUBLE;
  23. data.realVal = v;
  24. }
  25. Variant(std::string v){
  26. data.type = STRING;
  27. data.strVal = new std::string(v);
  28. }
  29. //the missing copy constructor
  30. Variant(Variant const& other)
  31. {
  32. *this = other;// redirect to the copy assignment
  33. }
  34.  
  35. ~Variant(){
  36. if(STRING == data.type){
  37. delete data.strVal;
  38. }
  39. }
  40.  
  41. Variant& operator = (const Variant& other){
  42. if(this != &other)
  43. {
  44. if(STRING == data.type){
  45. delete data.strVal;
  46. }
  47.  
  48. switch(other.data.type){
  49. case STRING:{
  50. data.strVal = new std::string(*(other.data.strVal));
  51. data.type = STRING;
  52. break;
  53. }
  54. default:{
  55. memcpy(this, &other, sizeof(Variant));
  56. break;
  57. }
  58. }
  59. }
  60. return *this;
  61. }
  62. Variant& operator = (int newVal){
  63. if(STRING == data.type){
  64. delete data.strVal;
  65. }
  66. data.type = INT;
  67. data.intVal= newVal;
  68. return *this;
  69. }
  70.  
  71. Variant& operator = (double newVal){
  72. if(STRING == data.type){
  73. delete data.strVal;
  74. }
  75. data.type = DOUBLE;
  76. data.realVal= newVal;
  77. return *this;
  78. }
  79.  
  80. Variant& operator = (std::string& newVal){
  81. if(STRING == data.type){
  82. delete data.strVal;
  83. }
  84. data.type = STRING;
  85. data.strVal= new std::string(newVal);
  86. return *this;
  87. }
  88. operator int&() {
  89. if(INT == data.type)
  90. {
  91. return data.intVal;
  92. }
  93. //do type conversion if you like
  94. throw std::runtime_error("bad cast");
  95. }
  96.  
  97. operator double&() {
  98. if(DOUBLE == data.type){
  99. return data.realVal;
  100. }
  101. //do type conversion if you like
  102. throw std::runtime_error("bad cast");
  103. }
  104. operator std::string&() {
  105. if(STRING == data.type){
  106. return *data.strVal;
  107. }
  108. throw std::runtime_error("bad cast");
  109. }
  110. private:
  111. enum Type{
  112. UNKOWN=0,
  113. INT,
  114. DOUBLE,
  115. STRING
  116. };
  117. struct{
  118. Type type;
  119. union
  120. {
  121. int intVal;
  122. double realVal;
  123. std::string* strVal;
  124. };
  125. } data;
  126. };
  127.  
  128.  
  129. int main(){
  130. Variant v("this is string");//string
  131. v=1;//int
  132. v=1.0;//double
  133. v=std::string("another string");//
  134. Variant v2; //unkown type
  135. v2=v;//string
  136. std::cout << (std::string&)v2 << std::endl;
  137. return 0;
  138. }
  139.  
  140. class Variant
  141. {
  142. private:
  143. enum StoreType
  144. {
  145. Integer,
  146. Float,
  147. String,
  148. }
  149. store_type;
  150.  
  151. union
  152. {
  153. int * as_integer;
  154. double * as_double;
  155. std::string * as_string;
  156. }
  157. store_pointer;
  158.  
  159. // convert to type
  160. void integer_to_double();
  161. void integer_to_string();
  162. void double_to_integer();
  163. void double_to_string();
  164. void string_to_integer();
  165. void string_to_double();
  166.  
  167. public:
  168.  
  169. ...
  170.  
  171. int & ToInt()
  172. {
  173. switch (store_type)
  174. {
  175. case Integer: break;
  176. case Double: double_to_integer(); break;
  177. case String: string_to_integer(); break;
  178. }
  179. return * as_integer;
  180. }
  181.  
  182. ...
  183.  
  184. }
  185.  
  186. class Variant {
  187. enum internaltype {stringtype, inttype, doubletype} curtype;
  188. std::string strdata; //can't be in union
  189. union {
  190. int intdata;
  191. double doubledata;
  192. };
  193. public:
  194. Variant() :curtype(inttype) {}
  195. Variant(const std::string& s) : curtype(stringtype), strdata(s) {}
  196. Variant(int i) : curtype(inttype) {intdata = i;}
  197. Variant(double d) : curtype(doubletype) {doubledata = d;}
  198.  
  199. std::string& ToString() {
  200. std::stringstream ss;
  201. switch(curtype) {
  202. case inttype:
  203. ss << intdata;
  204. ss >> stringdata;
  205. break;
  206. case doubletype:
  207. ss << doubledata;
  208. ss >> stringdata;
  209. break;
  210. }
  211. curtype = stringtype;
  212. return &strdata;
  213. }
  214. int& ToInt() {/*much the same*/}
  215. double& ToDouble() {/*much the same*/}
  216. };
  217.  
  218. #include <boost/any.hpp>
  219. #include <boost/lexical_cast.hpp>
  220. #include <string>
  221. #include <typeinfo>
  222.  
  223. class Variant
  224. {
  225. boost::any value;
  226. public:
  227. Variant(int n): value(n) {}
  228. Variant(double d): value(d) {}
  229. Variant(const std::string& s): value(s) {}
  230. Variant(const char* s): value(std::string(s)) {} //without this, string literals create ambiguities
  231.  
  232. int& ToInt() { return convert<int>();}
  233. double& ToDouble() { return convert<double>(); }
  234. std::string& ToString() { return convert<std::string>(); }
  235.  
  236. private:
  237. template <class T>
  238. T& convert()
  239. {
  240. if (typeid(T) != value.type()) { //otherwise no conversion required
  241. if (typeid(int) == value.type()) {
  242. value = boost::lexical_cast<T>(boost::any_cast<int>(value));
  243. }
  244. else if (typeid(double) == value.type()) {
  245. value = boost::lexical_cast<T>(boost::any_cast<double>(value));
  246. }
  247. else if (typeid(std::string) == value.type()) {
  248. value = boost::lexical_cast<T>(boost::any_cast<std::string>(value));
  249. }
  250. }
  251. return *boost::any_cast<T>(&value);
  252. }
  253. };
  254.  
  255. #include <iostream>
  256. using namespace std;
  257.  
  258. int main()
  259. {
  260. Variant a = 7;
  261. cout << "The answer is" + a.ToString() << endl; // should print "The answer is 7"
  262. a = "7.4";
  263. double &b = a.ToDouble();
  264. b += 1;
  265. cout << a.ToString() << endl; // should print 8.4
  266. }
  267.  
  268. class Variant
  269. {
  270. private:
  271. enum data_type {
  272. ...
  273. };
  274.  
  275. data_type variant_type;
  276.  
  277. union Data {
  278. char *string;
  279. int integer;
  280. double dbl;
  281. } data;
  282.  
  283. public:
  284. Variant(const int data);
  285. Variant(const double data);
  286. Variant(const char *data);
  287.  
  288. // I think that implementation of the constructors should be pretty straight forward.
  289.  
  290. int ToInt() const;
  291. double ToDouble() const;
  292. std::string ToString() const;
  293. };
  294.  
  295. class Variant
  296. {
  297. private:
  298. char data_string[16384];
  299.  
  300. public:
  301. Variant(const int data);
  302. Variant(const double data);
  303. Variant(const char *data);
  304.  
  305. // I think that implementation of the constructors should be pretty straight forward.
  306.  
  307. int ToInt() const;
  308. double ToDouble() const;
  309. std::string ToString() const;
  310. };
Advertisement
Add Comment
Please, Sign In to add comment