c++ - Code generation with macros: Class with members and constructor -


let's want define classes of following structure:

struct myclass {     int x;     bool y;     float z;     myclass(qvariantmap data) : x(data["x"]), y(data["y"]), z(data["z"]) {} }; 

as can see, have qvariantmap (something similar std::map<std::string, boost::variant<...>> of not familiar qt) want able construct such type no further knowledge of fields, hence convenient constructor should "deserialize" fields map.

i need several classes of style, , want definitions clean possible maximum maintainability (regarding typos in string keys), readability , automation.

i thought of macro structure following:

def_class(myclass)(     def_field(int, x)     def_field(bool, y)     def_field(float, z) ); 

i don't see problem when want generate fields not constructor (the other way around possible, i'll demonstrate former only):

#define def_class(classname) \     struct classname { \     _def_class_tail/*..."curry arguments"...*/ #define _def_class_tail(fields) \         fields \     } #define def_field(type, name) type name; 

i define first macro starts class definition , use "curry" technique forward second parentheses second macro puts contents of class definition (fields) , closes afterwards. way -- idea -- have access fields within second macro.

but how can output fields twice, 1 define actual fields , 1 output member initialization?

i know if define macro def_class_field in 2 different ways , "include" fields definition code above, 1 every macro definition, print them 1 after correctly. since field listing (and should) within class definition, cannot include twice.

are there other options?

i try avoid boost preprocessor library, if have nice solution uses that, go ahead. however, prefer simple solution, if there any.

here example not build struct cache values map, checks @ constructor map contains fields, discussed in comments of opening question.

#define def_class(classname) \     struct classname { \     classname(qvariantmap& map) {\     _def_class_tail/*..."curry arguments"...*/ #define _def_class_tail(fields) \         fields \     }}; #define chk_field(type, name) \     if (typeid(type)!=typeid(map[#name])) \     { throw std::runtime_error(#name" missing or wrong type");} def_class(myclass)(     chk_field(int, x)     chk_field(bool, y)     chk_field(float, z) ); 

this produces following preprocessor (after running through astyle):

struct myclass {    myclass(qvariantmap& map) {       if (typeid(int) != typeid(map["x"])) {          throw std::runtime_error("x"" missing or wrong type");       }       if (typeid(bool) != typeid(map["y"])) {          throw std::runtime_error("y"" missing or wrong type");       }       if (typeid(float) != typeid(map["z"])) {          throw std::runtime_error("z"" missing or wrong type");       }    } }; 

edit: i'm not 100% sure typeid comparisons work this, should straight forward replace check work.


Comments

Popular posts from this blog

java - Jmockit String final length method mocking Issue -

What is the difference between data design and data model(ERD) -

ios - Can NSManagedObject conform to NSCoding -