cbeck88/visit_struct

runtime versions of indexed access functions

mdimura opened this issue · 3 comments

It may be sometimes useful to have also runtime reflection. So I came up with some wrappers in GUI object properties editor code, like these:

#include "visit_struct/visit_struct.hpp"
#include <iostream>
#include <variant>
#include <string>

struct S {
    int n;
    float f;
    char c;
};
VISITABLE_STRUCT(S, n, f, c);

using var_type=std::variant<int,float,char>;

template<std::size_t I = 0, typename FuncT,typename T>
inline typename std::enable_if<I == visit_struct::field_count<T>(), void>::type
for_index(int, T&, FuncT)
{ }

template<std::size_t I = 0, typename FuncT,typename T>
inline typename std::enable_if<I < visit_struct::field_count<T>(), void>::type
for_index(int index, T& t, FuncT f)
{
    if (index == 0) f(visit_struct::get<I>(t));
    for_index<I + 1, FuncT>(index-1, t, f);
}

template<typename T>
var_type get_variant(const T& t,int i)
{
    var_type var;
    for_index(i,t,[&var](auto&& v) {
        var=v;
    });
    return var;
}

template<typename T>
void set_field(T& t, const var_type& var, int i)
{
    for_index(i,t,[&i,&var](auto&& prop) {
        std::visit([&prop](auto&& v) {
            prop=v;
        },var);
    });
}

int main()
{
    S s{42,3.14,'Z'};
    auto printer=[](auto&& v) {
        std::cout<<v<<'\n';
    };
    var_type var;
    var=get_variant(s,2);
    std::visit(printer,var);

    var=2.718f;
    set_field(s,var,1);
    var=get_variant(s,1);
    std::visit(printer,var);
    return 0;
}

It is far from complete and is probably not the best way to implement it, but shows the idea. Would it be useful to have similar wrappers as a part of visit_struct?

One issue is, std::variant is C++17, while visit_struct targets C++11.

Another issue is, lots of projects use lots of different variants, for example, std::variant is not strongly exception-safe so it isn't appropriate in many cases.

You could side-step that to some extent I suppose if you make it a variant containing references to the value actually contained in the struct instead of copies of those values?

I agree that this would be useful functionality, although it would expand the scope of visit_struct significantly. I'll write again with more thoughts.

Based on your examples, I've put together a minimum functional set of wrappers.

This looks like a good idea, I agree that we should have something like this as part of visit_struct.
Will write again soon