• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2018-2021 Antony Polukhin
2 //
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5 
6 // Example from https://github.com/apolukhin/magic_get/issues/21
7 
8 
9 // boost::pfr::for_each_field crashes when sizeof(MyConfig) > 248 (probably >= 256)
10 
11 #include <boost/pfr.hpp>
12 
13 #include <iostream>
14 #include <type_traits>
15 
16 template <typename T>
17 class CfgAttrib {
18 public:
19     using value_type = T;
20 
getAttrName() const21     const char* getAttrName() const { return name; }
getValue() const22     const T& getValue() const { return value; }
23 
24     static constexpr std::true_type is_config_field{};
25 
26     const char* const name;
27     T value;
28     //char dummy[8];
29 };
30 
31 
32 // a marker class for the code reflection
33 struct CfgSection {
34     const char* const name{ "UNNAMED" };
35     static constexpr std::false_type is_config_field{};
36 };
37 
38 // a marker class for the code reflection
39 struct CfgSubSection {
40     const char* const name{ "UNNAMED" };
41     static constexpr std::false_type is_config_field{};
42 };
43 
44 
45 // all configuration data apart from audio and midi devices, which is handled by special juce support
46 // the class is supposed to be iterated with boost::pfr library.
47 // Thus its members must met the requirements (aggregate initializeable)
48 class MyConfig {
49 public:
50     // Configuration / Section Data fields
51 
52     CfgSection                  sectionMain{ "section1" };
53     CfgAttrib<unsigned>         attr1{ "attr1", 1 };
54 
55     CfgSection                  section2{ "section2" };
56     CfgAttrib<unsigned>         attr3{ "attr3", 13 };
57     CfgAttrib<unsigned>         attr4{ "attr4", 2};
58     CfgAttrib<unsigned>         attr5{ "attr5", 0 };
59     CfgAttrib<unsigned>         attr6{ "attr6", 6 };
60 
61     CfgSection                  section3{ "section3" };
62     CfgAttrib<long long int>    attr7{ "attr7", 0 };
63 
64     CfgSection                  section4{ "section4" };
65     CfgAttrib<long long int>    attr8{ "attr8", 0 };
66     CfgAttrib<long long int>    attr9{ "attr9", 0 };
67     CfgAttrib<long long int>    attr10{ "attr10", 0 };
68 
69     CfgSection                  section5{ "section5" };
70     CfgAttrib<long long int>    attr11{ "attr11", 0 };
71 
72     CfgSection                  section666{ "section666" };
73     CfgAttrib<long long int>    attr12{ "attr12", 0 };
74     CfgAttrib<unsigned>         attr13{ "attr13", 0 };
75 };
76 
77 
78 
79 template <class T>
printer(const T & value,std::true_type)80 void printer(const T& value, std::true_type) {
81     std::cout << "- " << value.getAttrName() << ": " << value.getValue() << std::ends;
82 }
83 
84 template <class T>
printer(const T & value,std::false_type)85 void printer(const T& value, std::false_type) {
86     std::cout << "Section \"" << value.name << "\":" << std::ends;
87 }
88 
89 
main()90 int main() {
91     std::cout << "sizeof(MyConfig) = " << sizeof(MyConfig) << std::ends;
92 
93     MyConfig aCfg;
94     boost::pfr::for_each_field(aCfg, [](auto& value) {
95         printer(value, value.is_config_field);
96     });
97 
98 #if BOOST_PFR_USE_CPP17
99     boost::pfr::get<0>(aCfg); // also C1202
100 #endif
101 }
102