boostorg / hana

Your standard library for metaprogramming
http://boostorg.github.io/hana
Boost Software License 1.0
1.66k stars 217 forks source link

A proposal that works like BOOST_HANA_DEFINE/ADAPT_STRUCT and makes it 5x faster. #514

Open johnjohnlin opened 1 year ago

johnjohnlin commented 1 year ago

Hi developers, I have used BOOST_HANA_DEFINE_STRUCT in my project and find it very useful. Thanks for the great work. When I was using the library, I came up with an idea that makes a similar BOOST_HANA_DEFINE_STRUCT, with much shorter compile time. I made a proof-of-concept and it shows 5x time saving and 4x memory saving (will show later).

Since Hana is a library that features fast compile time, I think my proposal can help makes Hana a better library, and I want to make contribution.

The proposal is a macro like BOOST_HANA_ADAPT_STRUCT.

struct MyStruct {
    int a;
    bool b;
    string c;
    vector<int> d;
    MAKE_NAMEDTUPLE(a, b, c, d)
};
MyStruct my;

Using this macro, MyStruct almost becomes a tuple, bound with member name.

This acts like python namedtuple, which allows iterating all members/names using fold expression (c++17) or recursion (pre c++17).

For example, this namedtuple allowed me to create a generic argument parser works as below:

int argc;
char **argv;
// Input
argc = 14
argv = ./main.exe --a 12 --b --d [ 1 2 3 ] --c mystring --garbage extra
Argparse(my, argc, argv)
// Output
argc = 3
argv = ./main.exe --garbage extra

Or I can implement a generic JSON print function like the example in Hana::Struct.

The implemention of namedtuple is simple. With boost.preprocessor I only need 10 lines of macro, which is expanded to:

struct MyStruct {
    int a;
    bool b;
    string c;
    vector<int> d;
    // The following code can be generated by boost preprocessor
    // by MAKE_NAMEDTUPLE(a, b, c, d)
    auto& get(integral_constant<unsigned, 0>) { return a; }
    auto& get(integral_constant<unsigned, 1>) { return b; }
    auto& get(integral_constant<unsigned, 2>) { return c; }
    auto& get(integral_constant<unsigned, 3>) { return d; }
    static constexpr unsigned num_members = 4;
    const char* get_name(unsigned x) {
        static const char* names[] = {"a", "b", "c", "d", ""};
        return names[x];
    }
    template<unsigned x> auto& get() { return get(integral_constant<unsigned, x>{}); }
};

The benchmark is accessible here. How do you think about this proposal? If you consider this is suitable, can you instruct me some ways to glue this namedtuple into Hana?

ldionne commented 1 year ago

Hi, and thanks for your interest!

I think the best way forward here would be to integrate with Boost.Describe as discussed in #498. WDYT?

johnjohnlin commented 1 year ago

Agree, seems that Boost.Describe provides sufficient functionalities for type reflection. I shall avoid inventing the wheel.

Maybe I can try whether using Boost.Describe can also provide good compile time performance.