fork download
  1.  
  2.  
  3. #include <type_traits>
  4. #include <string>
  5. #include <iostream>
  6.  
  7. // Данные
  8. struct Base
  9. {};
  10.  
  11. struct A: Base
  12. {
  13. std::string name = "name_A";
  14. };
  15.  
  16. struct B: Base
  17. {
  18. std::string name = "name_B";
  19. std::string description = "desc_B";
  20. };
  21.  
  22. struct C: Base
  23. {
  24. std::string description = "desc_C";
  25. };
  26.  
  27. class MetaAll;
  28.  
  29.  
  30. class MetaName
  31. {
  32. public:
  33.  
  34. inline const std::string& name() const { return *_name; }
  35.  
  36. public:
  37.  
  38. MetaName()
  39. : _name{&_const_name_empty}
  40. {};
  41.  
  42. template<
  43. class T,
  44. std::enable_if_t<!std::is_base_of<MetaAll, T>::value>* = nullptr // for VC
  45. >
  46. explicit MetaName(const T& t)
  47. : _name{&t.name}
  48. {}
  49.  
  50. MetaName(const MetaName&) = default;
  51. MetaName& operator=(const MetaName&) = default;
  52.  
  53. private:
  54.  
  55. static const std::string _const_name_empty;
  56. const std::string* _name;
  57. };
  58. const std::string MetaName::_const_name_empty;
  59.  
  60.  
  61. class MetaDescription
  62. {
  63. public:
  64.  
  65. inline const std::string& description() const { return *_description; }
  66.  
  67. public:
  68.  
  69. MetaDescription()
  70. : _description{&_const_description_empty}
  71. {};
  72.  
  73. template<
  74. class T,
  75. std::enable_if_t<!std::is_base_of<MetaAll, T>::value>* = nullptr // for VC
  76. >
  77. explicit MetaDescription(const T& t)
  78. : _description{&t.description}
  79. {}
  80.  
  81. MetaDescription(const MetaDescription&) = default;
  82. MetaDescription& operator=(const MetaDescription&) = default;
  83.  
  84. private:
  85.  
  86. static const std::string _const_description_empty;
  87. const std::string* _description;
  88. };
  89. const std::string MetaDescription::_const_description_empty;
  90.  
  91.  
  92.  
  93.  
  94. struct FieldNameTag {};
  95. struct FieldDescriptionTag {};
  96. const FieldNameTag FieldName;
  97. const FieldDescriptionTag FieldDescription;
  98.  
  99.  
  100. class MetaAll: public MetaName, public MetaDescription
  101. {
  102. public:
  103.  
  104. MetaAll() = default;
  105. MetaAll(const MetaAll&) = default;
  106. MetaAll& operator=(const MetaAll&) = default;
  107.  
  108. template<class T>
  109. MetaAll(const T& t, FieldNameTag)
  110. : MetaName(t)
  111. , MetaDescription()
  112. {}
  113.  
  114. template<class T>
  115. MetaAll(const T& t, FieldDescriptionTag)
  116. : MetaName()
  117. , MetaDescription(t)
  118. {}
  119.  
  120. template<class T>
  121. MetaAll(const T& t, FieldNameTag, FieldDescriptionTag)
  122. : MetaName(t)
  123. , MetaDescription(t)
  124. {}
  125. };
  126.  
  127.  
  128.  
  129. int main()
  130. {
  131. const A a;
  132. const B b;
  133. const C c;
  134.  
  135. for (MetaName meta : {MetaName(a), MetaName(b)})
  136. {
  137. std::cout << meta.name() << std::endl;
  138. }
  139.  
  140. for (MetaDescription meta : {MetaDescription(b), MetaDescription(c)})
  141. {
  142. std::cout << meta.description() << std::endl;
  143. }
  144.  
  145. for (MetaAll meta : {MetaAll(a, FieldName), MetaAll(b, FieldName, FieldDescription), MetaAll(c, FieldDescription)})
  146. {
  147. std::cout << meta.name() << " <-> " << meta.description() << std::endl;
  148. }
  149.  
  150. // MetaAll meta(a, FieldDescription); -> Compile time error
  151.  
  152. return 0;
  153. }
  154.  
Success #stdin #stdout 0s 15240KB
stdin
Standard input is empty
stdout
name_A
name_B
desc_B
desc_C
name_A <-> 
name_B <-> desc_B
 <-> desc_C