fork download
  1. #include <iostream>
  2. #include <map>
  3. #include <memory>
  4. #include <string>
  5.  
  6. #define CONCAT(x, y) CONCAT_(x, y)
  7. #define CONCAT_(x, y) x ## y
  8.  
  9. #define PAR(type, name, descr) \
  10. type name; \
  11. const bool CONCAT(doRegistration, __LINE__) = []() { \
  12.   entries.emplace(#name, \
  13.   std::unique_ptr<BaseEntry>( \
  14.   new Entry<Model, type>{ type##_type, &Model::name })); \
  15.   return true; \
  16. }();
  17.  
  18. enum ParType { double_type, int_type };
  19.  
  20. class Model;
  21.  
  22. struct BaseEntry
  23. {
  24. BaseEntry(ParType type) : type(type) {}
  25. ParType type;
  26.  
  27. template <typename C, typename T>
  28. T & get(C &c);
  29. };
  30.  
  31. template <typename C, typename T>
  32. struct Entry : BaseEntry
  33. {
  34. Entry(ParType type, T C::* ptr) : BaseEntry(type), ptr(ptr) {}
  35. T C::* ptr;
  36. };
  37.  
  38. template <typename C, typename T>
  39. T & BaseEntry::get(C &c)
  40. {
  41. return c.*static_cast<Entry<C, T>*>(this)->ptr;
  42. }
  43.  
  44. class Model
  45. {
  46. public:
  47. Model() : a(1.0), b(2) {}
  48.  
  49. static std::map<std::string, std::unique_ptr<BaseEntry>> entries;
  50.  
  51. PAR(double, a, "какой то параметр");
  52. PAR(int, b, "и еще один параметр");
  53. };
  54.  
  55. std::map<std::string, std::unique_ptr<BaseEntry>> Model::entries;
  56.  
  57. int
  58. main(void)
  59. {
  60. Model m;
  61. for (const auto &e : m.entries) {
  62. std::cout << e.first << std::endl;
  63. switch (e.second->type) {
  64. case double_type:
  65. e.second->get<Model, double>(m) = 10.1;
  66. std::cout << e.second->get<Model, double>(m) << std::endl;
  67. break;
  68. case int_type:
  69. std::cout << e.second->get<Model, int>(m) << std::endl;
  70. break;
  71. }
  72. }
  73. return 0;
  74. }
  75.  
Success #stdin #stdout 0s 3472KB
stdin
Standard input is empty
stdout
a
10.1
b
2