text: // Copyright (c) 2018-2021 Antony Polukhin
  //
  // Distributed under the Boost Software License, Version 1.0. (See accompanying
  // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  
  // Example from https://github.com/apolukhin/magic_get/issues/21
  
  
  // boost::pfr::for_each_field crashes when sizeof(MyConfig) > 248 (probably >= 256)
  
  #include <boost/pfr.hpp>
  
  #include <iostream>
  #include <type_traits>
  
  template <typename T>
  class CfgAttrib {
  public:
      using value_type = T;
  
      const char* getAttrName() const { return name; }
      const T& getValue() const { return value; }
  
      static constexpr std::true_type is_config_field{};
  
      const char* const name;
      T value;
      //char dummy[8];
  };
  
  
  // a marker class for the code reflection
  struct CfgSection {
      const char* const name{ "UNNAMED" };
      static constexpr std::false_type is_config_field{};
  };
  
  // a marker class for the code reflection
  struct CfgSubSection {
      const char* const name{ "UNNAMED" };
      static constexpr std::false_type is_config_field{};
  };
  
  
  // all configuration data apart from audio and midi devices, which is handled by special juce support
  // the class is supposed to be iterated with boost::pfr library.
  // Thus its members must met the requirements (aggregate initializeable)
  class MyConfig {
  public:
      // Configuration / Section Data fields
  
      CfgSection                  sectionMain{ "section1" };
      CfgAttrib<unsigned>         attr1{ "attr1", 1 };
  
      CfgSection                  section2{ "section2" };
      CfgAttrib<unsigned>         attr3{ "attr3", 13 };
      CfgAttrib<unsigned>         attr4{ "attr4", 2};
      CfgAttrib<unsigned>         attr5{ "attr5", 0 };
      CfgAttrib<unsigned>         attr6{ "attr6", 6 };
  
      CfgSection                  section3{ "section3" };
      CfgAttrib<long long int>    attr7{ "attr7", 0 };
  
      CfgSection                  section4{ "section4" };
      CfgAttrib<long long int>    attr8{ "attr8", 0 };
      CfgAttrib<long long int>    attr9{ "attr9", 0 };
      CfgAttrib<long long int>    attr10{ "attr10", 0 };
  
      CfgSection                  section5{ "section5" };
      CfgAttrib<long long int>    attr11{ "attr11", 0 };
  
      CfgSection                  section666{ "section666" };
      CfgAttrib<long long int>    attr12{ "attr12", 0 };
      CfgAttrib<unsigned>         attr13{ "attr13", 0 };
  };
  
  
  
  template <class T>
  void printer(const T& value, std::true_type) {
      std::cout << "- " << value.getAttrName() << ": " << value.getValue() << std::ends;
  }
  
  template <class T>
  void printer(const T& value, std::false_type) {
      std::cout << "Section \"" << value.name << "\":" << std::ends;
  }
  
  
  int main() {
      std::cout << "sizeof(MyConfig) = " << sizeof(MyConfig) << std::ends;
  
      MyConfig aCfg;
      boost::pfr::for_each_field(aCfg, [](auto& value) {
          printer(value, value.is_config_field);
      });
  
  #if BOOST_PFR_USE_CPP17
      boost::pfr::get<0>(aCfg); // also C1202
  #endif
  }
  