Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 21st, 2012  |  syntax: None  |  size: 7.40 KB  |  hits: 10  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  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. };