0

I am trying to achieve the following: Given a POD struct I want to generate compile time metadata on the struct automatically (i.e I don't want to have to register every field by hand).

The metadata I need is just the number of fields and the byte size of each field.

So for example for the struct:

struct MyData
{
    float field1;
    int field2;
}

All we need is FIELD_NUM(MyData) to return 2 and FIELD_SIZE(MyData, 0) to return 4.

My current approach is terrible. I don't even use the built in preprocessor, I have a python parser that searches for a comment on top of the structure and it builds a dictionary of all registered structures, it then replaces the patterns in the code with their numeric values. But this is very limited, for example I don't even handle templates because at that point I might as well make my own C++ compiler.

Using templated meta programming

Ok so in the comments someone suggested a very interesting video that I am watching. It suggests that to get the number of fields in a POD you can do this:

template <std::size_t I>
struct ubiq_constructor
{
    template <class Type>
    constexpr operator Type&() const noexcept;
};

template <class T, std::size_t I0, std::size_t... I>
constexpr auto detect_fields_count(std::size_t& out, std::index_sequence<I0, I...>)
    -> decltype( T{ ubiq_constructor<I0>{}, ubiq_constructor<I>{}... } )
{ out = sizeof...(I) + 1; }

template <class T, std::size_t... I>
constexpr void detect_fields_count(std::size_t& out, std::index_sequence<I...>) {
    detect_fields_count<T>(out, std::make_index_sequence<sizeof...(I) - 1>{});
}

The gist of it is, try to initialize the struct with a number of parameters equal to the struct size, if that fails, reduce the parameters by one, keep going until the number of parameters matches the fields in the struct.

However when I try to call it like this:

struct POD {
    int f1;
    float f2;
    char h;
};


    std::size_t size;
    detect_fields_count<POD>(size, std::make_index_sequence<sizeof(POD)>());
    cout << "size:" << size << endl;

I get a segmentation fault on pre-initialization. How do you call those functions?

Makogan
  • 8,208
  • 7
  • 44
  • 112
  • 2
    Possibly related: [How do I get the number of members in a structure?](https://stackoverflow.com/q/12194793/10871073). – Adrian Mole Aug 16 '20 at 16:53
  • Remember that the compiler *may* insert padding before/between/after members. – Jesper Juhl Aug 16 '20 at 16:55
  • Did you try doing this the other way around: writing the metadata, then using a simple parser to robo-generate C++ code with the struct definition, from your metadata? – Sam Varshavchik Aug 16 '20 at 17:14
  • @SamVarshavchik Unfortunately for the kind of use case I am looking for that;s not achievable. I want to be able to handle source code POD structs, and I need the info at compile time, so no parsing allowed. – Makogan Aug 16 '20 at 19:13
  • You'll be surprised to learn that it's trivially possible, using any common build system, to arrange for parsing scripts to be executed before the code is compiled. I just happen to be doing exactly that in one of my libraries. The metadata's original source is in XML, and the build system runs an XSLT stylesheet to robo-generate C++ `struct` declarations, together with C++ reflection-type metadata, which then gets normally compiled. – Sam Varshavchik Aug 16 '20 at 19:16
  • I don't think you understand my point however. I need to be able to handle definitions in C++ source files. I.e. I cannot assume I can create the XML for the structures I am handling/ It is possible I am given an already defined library and I need to handle it's data. At that point creating XML would be redundant as I could just generate whatever data I need directly. – Makogan Aug 16 '20 at 19:25
  • @AdrianMole that's an interesting resource for sure, but how do you call the functions? That seems to be missing from both the anser and the video – Makogan Aug 17 '20 at 00:05

0 Answers0