veselink1 / refl-cpp

Static reflection for C++17 (compile-time enumeration, attributes, proxies, overloads, template functions, metaprogramming).
https://veselink1.github.io/refl-cpp/md__introduction.html
MIT License
1.05k stars 76 forks source link

Question. a generic getter function for reflected type #75

Closed enojoker closed 1 year ago

enojoker commented 1 year ago

first of all, thanks for this great library. I'm a bit of a newbie to c++ metaprogramming. Hope my question is clear.

Following your serialization example, I tried to write a getter function that takes a member's name as input for a reflected type. The code below is what I got so far. It feels a bit awkward for a getter function to iterator through all members to return the value.

I'm thinking about doing some compile time mapping between member variable name and member index so that I can use static constexpr decltype(auto) get(U&& target) noexcept from field_descriptor. But couldn't get it working ...

Just wondering if you were to implement a generic getter function how would you do it?

Many thanks!

struct serializable : refl::attr::usage::field, refl::attr::usage::function
{

};

struct Point
{
    float x;
    float y;

};

REFL_TYPE(Point, bases<>)
    REFL_FIELD(x, serializable()) // here we use serializable only as a maker
    REFL_FIELD(y, serializable())
REFL_END

template <typename T, typename fld>
fld get(T& value, const std::string& fld_name )
{
    fld res;
    // iterate over the members of T
    for_each(refl::reflect(value).members, [&](auto member)
    {
        // is_readable checks if the member is a non-const field
        // or a 0-arg const-qualified function marked with property attribute
        if constexpr (is_readable(member) && refl::descriptor::has_attribute<serializable>(member))
        {
            if (strcmp(get_display_name(member), fld_name.c_str()) == 0)
                res = member(value);
        }
    });
    return res;
}

int main(){
    Point p{1,2};
    double p_x = get<decltype(p),double>(p, "x");
    std::cout << "x: " << p_x << std::endl;
    return 0;
}
veselink1 commented 1 year ago

some compile time mapping between member variable name

It might not be possible to do this at compile time if the member variable name is not a compile-time constant.

There is refl::runtime::invoke which does what you're attempting to do in your example.