When declaring a boost pfr char array in structure, a compile error occurs

49 views Asked by At

When declaring a char array in structure, a compile error occurs at a certain size In Boost 1.84 Requires C++20.

#include <iostream>
#include <string>

#include <boost/pfr.hpp>
#include <boost/pfr/core.hpp>
#include <boost/pfr/core_name.hpp>
#include <boost/type_index.hpp>

struct Foo
{
    //std::string attr01;    // Compile OK
    //std::string attr02;    // Compile OK 
    //std::string attr03;    // Compile 0K

    char attr01[600];      // Compile Error
    //char attr02[100];
    //char attr03[200];
    //char attr04[600];
    //char attr05[600];
    //char attr06[600];
    //char attr07[600];
    //char attr08[600];
    //char attr09[600];
    //char attr10[600];
    //char attr11[600];
    //char attr12[600];
    //char attr13[600];
    //char attr14[600];
    //char attr15[600];
    //char attr16[600];
    //char attr17[600];
    //char attr18[600];
    //char attr19[600];
    //char attr20[600];
};

int main() {

    Foo foo;
    auto names = boost::pfr::names_as_array<Foo>();

    boost::pfr::for_each_field(foo, [&names](const auto& field, std::size_t idx) {
        std::cout << names[idx] << " : " << boost::typeindex::type_id_runtime(field) << "\n";
    });

    return 0;
}

OUTPUT compile error occur error : C2672 'boost::pfr::detail::name_of_field': There are no matching overloaded functions.

1

There are 1 answers

0
sehe On

From the docs:

Boost.PFR library works with types that satisfy the requirements of SimpleAggregate: aggregate types without base classes, const fields, references, or C arrays:

And

The library may work with aggregates that don't satisfy the requirements of SimpleAggregate, but the behavior tends to be non-portable.

And further down:

Details on Limitations The Boost.PFRs reflection has some limitations that depend on a C++ Standard and compiler capabilities:

  • Static variables are ignored
  • T must be aggregate initializable without base classes
  • if T contains C arrays then the result of reflection may differ depending on the C++ version and library configuration
  • Additional limitations if BOOST_PFR_USE_CPP17 == 0:
    • Non of the member fields should have a template constructor from one parameter.
    • Additional limitations if BOOST_PFR_USE_LOOPHOLE == 0:
      • T must be constexpr aggregate initializable and all its fields must be constexpr default constructible
      • boost::pfr::get, boost::pfr::structure_to_tuple, boost::pfr::structure_tie, boost::pfr::tuple_element require T to be a POD type with built-in types only.

Indeed, avoid the C-style arrays. Use std::array instead. You can force the issue by wrapping in something like a tuple:

Live On Coliru

#include <boost/pfr.hpp>
#include <boost/type_index.hpp>
#include <iostream>

static auto constexpr N = 600;
struct Foo { std::tuple<char[N]> forced; };
struct Bar { std::array<char, N> array; };

template <typename T>
static void test(T obj) {
    auto names = boost::pfr::names_as_array<T>();

    boost::pfr::for_each_field(obj, [&names](auto const& field, std::size_t idx) {
        std::cout << names[idx] << " : " << boost::typeindex::type_id_runtime(field) << "\n";
    });
}

int main() {
    test(Foo{});
    test(Bar{});
}

Printing e.g.

forced : std::tuple<char [600]>
array : std::array<char, 600ul>