Skip to content

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

Open
@johnjohnlin

Description

@johnjohnlin

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?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions