1// Copyright (c) 2018-2024 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/boostorg/pfr/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
16template <typename T>
17class CfgAttrib {
18public:
19 using value_type = T;
20
21 const char* getAttrName() const { return name; }
22 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
33struct 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
39struct 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)
48class MyConfig {
49public:
50 // Configuration / Section Data fields
51
52 CfgSection sectionMain{ .name: "section1" };
53 CfgAttrib<unsigned> attr1{ .name: "attr1", .value: 1 };
54
55 CfgSection section2{ .name: "section2" };
56 CfgAttrib<unsigned> attr3{ .name: "attr3", .value: 13 };
57 CfgAttrib<unsigned> attr4{ .name: "attr4", .value: 2};
58 CfgAttrib<unsigned> attr5{ .name: "attr5", .value: 0 };
59 CfgAttrib<unsigned> attr6{ .name: "attr6", .value: 6 };
60
61 CfgSection section3{ .name: "section3" };
62 CfgAttrib<long long int> attr7{ .name: "attr7", .value: 0 };
63
64 CfgSection section4{ .name: "section4" };
65 CfgAttrib<long long int> attr8{ .name: "attr8", .value: 0 };
66 CfgAttrib<long long int> attr9{ .name: "attr9", .value: 0 };
67 CfgAttrib<long long int> attr10{ .name: "attr10", .value: 0 };
68
69 CfgSection section5{ .name: "section5" };
70 CfgAttrib<long long int> attr11{ .name: "attr11", .value: 0 };
71
72 CfgSection section666{ .name: "section666" };
73 CfgAttrib<long long int> attr12{ .name: "attr12", .value: 0 };
74 CfgAttrib<unsigned> attr13{ .name: "attr13", .value: 0 };
75};
76
77
78
79template <class T>
80void printer(const T& value, std::true_type) {
81 std::cout << "- " << value.getAttrName() << ": " << value.getValue() << std::ends;
82}
83
84template <class T>
85void printer(const T& value, std::false_type) {
86 std::cout << "Section \"" << value.name << "\":" << std::ends;
87}
88
89
90int main() {
91 std::cout << "sizeof(MyConfig) = " << sizeof(MyConfig) << std::ends;
92
93 MyConfig aCfg;
94 boost::pfr::for_each_field(value&: aCfg, func: [](auto& value) {
95 printer(value, value.is_config_field);
96 });
97
98#if BOOST_PFR_USE_CPP17
99 boost::pfr::get<0>(val&: aCfg); // also C1202
100#endif
101}
102

source code of boost/libs/pfr/test/core/run/error_pfr_c1202.cpp