Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
johnjohnlin opened this issue Feb 1, 2023 · 2 comments

Comments

@johnjohnlin
Copy link

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.

  • my.get<0>() is a
  • my.get<1>() is b
  • my.get<2>() is c
  • my.get<3>() is d
  • MyStruct::get_name(0) is "a"
  • MyStruct::get_name(1) is "b"
  • MyStruct::get_name(2) is "c"
  • MyStruct::get_name(3) is "d"
  • MyStruct::num_members is 4

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
Copy link
Member

ldionne commented Mar 13, 2023

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
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants