MetaStuff icon indicating copy to clipboard operation
MetaStuff copied to clipboard

Add EnumMember type to MetaStuff.

Open iamPHEN opened this issue 9 years ago • 7 comments

Adds CMakeLists.txt for example for easier compilation.

Documentation is being added as we speak, putting code up for review so any changes needed to be made will be made.

EnumMember is implements a toString and fromString to convert Enum types from and to strings instead of by numeric number.

Implementation is rough, as the map is generated per-clas,, any ideas on how to move it to per-enum?Unless theres a use case for to map the same enum as different string values....

iamPHEN avatar Jul 30 '16 16:07 iamPHEN

This is great. Can we merge it?

aggsol avatar Mar 13 '18 09:03 aggsol

I kinda feel bad for not giving it enough attention and forgetting about it. :( @iamPHEN, are you still interested in this? There are some thing that need to be fixed and I'll be willing to merge.

Otherwise I can take your idea and implement it myself with all things I want to see here.

eliasdaler avatar Mar 13 '18 21:03 eliasdaler

This feature would also be very important for me.

Nightmare82 avatar May 24 '18 09:05 Nightmare82

I have more free time now, so I'll give it a closer look in a few days. :)

eliasdaler avatar May 24 '18 09:05 eliasdaler

That's great, thanks!

Nightmare82 avatar May 24 '18 15:05 Nightmare82

Still thinking about the best way to handle enum members... they're tricky!

As a temporary workaround, you can use this:

enum class Color
{
    Red, Blue
};

class Person {
    /* ... */

    std::string getFavouriteColorString() const
    {
        switch (favouriteColor) {
            case Color::Red:
                return "Red";
            case Color::Blue:
                return "Blue";
        }
    }

    void setFavouriteColorByString(std::string str)
    {
        if (str == "Red") {
            favouriteColor = Color::Red;
        } else if (str == "Blue") {
            favouriteColor = Color::Blue;
        }
    }

};

template <>
inline auto registerMembers<Person>()
{
    return members(
        /* ... */
        member("favouriteColor", &Person::getFavouriteColorString,
                                 &Person::setFavouriteColorByString)
    );
}

It's possible to replace std::string with const char* if you want, but that doesn't work with JSON example (deserialization only, serialization works fine), and it's pretty hard to fix it at the moment. :)

eliasdaler avatar Jun 03 '18 14:06 eliasdaler

Another solution is to change serializer/deserializer to call another function if the member is enum. For example:

template <typename Class,
    typename>
json serialize(const Class& obj)
{
    json value;
    meta::doForAllMembers<Class>(
        [&obj, &value](auto& member)
        {
            auto& valueName = value[member.getName()];
            using MemberT = meta::get_member_type<decltype(member)>;
            if constexpr (!std::is_enum_v<MemberT>) {
                ...
            } else {
                valueName = enumToString(member.get(obj));
            }
        }
    );
    return value;
}

And now, we'll have to define enumToString function and an overload for Color like this:

std::string enumToString<Color>(const Color& color)
{
    switch (color) {
        case Color::Red:
            return "Red";
        case Color::Blue:
            return "Blue";
    }
}

And we register Color member like this:

member("favouriteColor", &Person::favouriteColor)

eliasdaler avatar Jun 03 '18 14:06 eliasdaler