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