programming languages - How change class of a C++ object (implementing a variadic type) -


first off: know bad idea change object's class, i'm implementing own programming language, , has variables can contain values of type, , change type @ will, please assume i'm not beginner not understanding oo basics.

currently, implement variant variables in c. each 1 has pointer table of function pointers, containing functions setasint(), setasstring() etc., followed instance variables in c++. objects same size.

when variable contains string , assigns int it, manually call destructor, change table of function pointers point table used variadic int values, , then set int instance variable.

this bit hard maintain, every time add new type, have add new table of function pointers , fill out all function pointers in it. structs of function pointers seem badly type-checked, , missing fields don't lead complaints, can accidentally forget 1 pointer in list , interesting crashes. also, have repeat function pointers same in types.

i'd implement variadic types in c++ instead, lot of type-checking , inheriting default behaviours done me compiler. there safe way this?

ps - know create wrapper object , use new allocate new object, can't have additional allocation overhead every int variable on stack.

pps - code needs portable across linux, mac, ios , windows now, if has standard c++ solution, better.

ppps - list of types extensible, predetermined @ compile-time. base layer of language defines basic types, host application language compiled adds few more types.

usage example:

cppvariant somenum(42); // creates cppvariantint.  cout << "original int: " << somenum->getasint()     << " (" << somenum->getasdouble() << ")" << endl;  somenum->setasint(700); // setter call.  cout << "changed int: " << somenum->getasint()     << " (" << somenum->getasdouble() << ")" << endl;  somenum->setasdouble(12.34); // calls destructor on cppvariantint , constructor on cppvariantdouble(12.34).  cout << "converted double: " << somenum->getasint()     << " (" << somenum->getasdouble() << ")" << endl; // getasint() on cppvariantdouble() rounds, or whatever. 

(imagine beyond double , int, there other types in future, strings or booleans, caller of getasint()/setasint() shouldn't have know stored as, long can converted @ runtime)

here solution based on type-erasure, union , template specializations.
i'm not sure fits requirements.
anyway, here gets:

  • anything placed on dynamic storage
  • no hierarchy required

you can improve further reduce amount of code, aims serve base point start.

it follows minimal, working example based on intended use in question:

#include<iostream>  class cppvariant {     union var {         var(): i{0} {}         int i;         double d;     };      using asintf = int(*)(var);     using asdoublef = double(*)(var);      template<typename from, typename to>     static protoas(var);  public:     cppvariant(int);     cppvariant(double);      int getasint();     double getasdouble();      void setasint(int);     void setasdouble(double);  private:     var data;     asintf asint;     asdoublef asdouble;  };  template<> int cppvariant::protoas<int, int>(var data) {     return data.i; }  template<> int cppvariant::protoas<double, int>(var data) {     return int(data.d); }  template<> double cppvariant::protoas<int, double>(var data) {     return double(data.i); }  template<> double cppvariant::protoas<double, double>(var data) {     return data.d; }  cppvariant::cppvariant(int i)     : data{},       asint{&protoas<int, int>},       asdouble{&protoas<int, double>} { data.i = i; }  cppvariant::cppvariant(double d)     : data{},       asint{&protoas<double, int>},       asdouble{&protoas<double, double>} { data.d = d; }  int cppvariant::getasint() { return asint(data); } double cppvariant::getasdouble() { return asdouble(data); }  void cppvariant::setasint(int i) {     data.i = i;     asint = &protoas<int, int>;     asdouble = &protoas<int, double>; }  void cppvariant::setasdouble(double d) {     data.d = d;     asint = &protoas<double, int>;     asdouble = &protoas<double, double>; }  int main() {     cppvariant somenum(42);     std::cout << "original int: " << somenum.getasint() << " (" << somenum.getasdouble() << ")" << std::endl;     somenum.setasint(700);     std::cout << "changed int: " << somenum.getasint() << " (" << somenum.getasdouble() << ")" << std::endl;     somenum.setasdouble(12.34);     std::cout << "converted double: " << somenum.getasint() << " (" << somenum.getasdouble() << ")" << std::endl; } 

Comments

Popular posts from this blog

php - How to display all orders for a single product showing the most recent first? Woocommerce -

asp.net - How to correctly use QUERY_STRING in ISAPI rewrite? -

angularjs - How restrict admin panel using in backend laravel and admin panel on angular? -