stephenberry / glaze

Extremely fast, in memory, JSON and interface library for modern C++
MIT License
1.13k stars 115 forks source link

Using enum type as the key for enum values of a struct #1117

Open bimalgaudel opened 3 months ago

bimalgaudel commented 3 months ago

The piece of code below does exactly what I want. However, I want to streamline the process of constructing MyType::glaze::value so that I do not have to enumerate all the pointers to the members as I have done here. Is it possible? Thanks.

enum struct MyEnum { First, Second };

namespace glz {
template <>
struct meta<MyEnum> {
  using enum MyEnum;
  static constexpr auto value = enumerate(First, Second);
};
}  // namespace glz

// MyType serializes to:
// {"x":0,"y":0,"MyEnum":"First"}
struct MyType {
  int x{};
  int y{};
  MyEnum me{MyEnum::First};
  struct glaze {
    static constexpr auto value = glz::object(&MyType::x,           //
                                              &MyType::y,           //
                                              glz::name_v<MyEnum>,  //
                                              &MyType::me);
  };
};
stephenberry commented 3 months ago

If you namespace your MyEnum type, then you can rename your me field to MyEnum

struct MyType {
  int x{};
  int y{};
  ::MyEnum MyEnum{MyEnum::First};
};

Now your type can be reflected and has the name you want.

Here is an example on compiler explorer: https://gcc.godbolt.org/z/T4WrhK7o3

Of course, you may not want this name in C++, in which case you will have to use your current solution.

bimalgaudel commented 3 months ago

Thank you for the response. That solution still requires to manually type-in the matching identifier as a member variable of MyType. I think what I want is to be able to iterate through key-value pair in reflection of MyType and update the key if the reflected type corresponding to the key is a C++ enum type.

stephenberry commented 3 months ago

I think what I want is to be able to iterate through key-value pair in reflection of MyType and update the key if the reflected type corresponding to the key is a C++ enum type.

This is a cool idea, and I'll keep this issue open as I consider it more. This would be another compile time option to enable, which would prevent the overhead of checking for the enum at compile time if the option wasn't enabled.

bimalgaudel commented 3 months ago

For more context, I have created this on Compiler Explorer.

The current output is:

{"num":0,"mylib::MyEnum":"First","mylib::MyFlag":"Yes"}.

But what I would ideally like is to remove the leading mylib:: string from the json keys of the output. I can currently achieve that by using glz::short_name_v, defined in the linked snippet, instead of glz::name_v when AppContext::glz::value is constructed to get:

{"num":0,"MyEnum":"First","MyFlag":"Yes"}.

The motivation behind this feature is to be able to obtain some app context from the user in json format then the main function will interpret that context. It would be cumbersome to have the user type in all the namespaces. In the same vein, the member variable names AppContext::e, AppContext::f might be renamed in the future, so it's not ideal to have the user spell them out in the context specification.