getml / reflect-cpp

A C++20 library for fast serialization, deserialization and validation using reflection. Supports JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML / msgpack.org[C++20]
https://getml.github.io/reflect-cpp/
MIT License
821 stars 65 forks source link

Access member given an object and a `MetaField` #73

Closed Klaim closed 3 months ago

Klaim commented 3 months ago

I didnt find any way given a MetaField (obtained in some other parts of the code through rfl::fields<T>()) and an instance of an object of the type which has that field, to access the right field in that object that match that meta field. I realize it is possible to do that IFF you kept track of teh associated field index from the point you called rfl::fields<T>() to the point where you need to access that member on the given object. But I expected to be able to do that just by keeping the MetaField around. Am I correct that there is currently no way to do that? If so this is a feature request :)

liuzicheng1987 commented 3 months ago

You are right.

At the moment this isn't possible, because in order to be able to do that, the MetaField would have to store either the original field name or the index at compile time. This would imply that every MetaField is its own type, which means couldn't just return a vector of MetaFields.

Could you explain the larger context of what you are trying to do? I suspect that what you are looking for is covered be .apply(...), .transform(...) or .and_then(...).

Klaim commented 3 months ago

At the moment this isn't possible, because in order to be able to do that, the MetaField would have to store either the original field name or the index at compile time. This would imply that every MetaField is its own type, which means couldn't just return a vector of MetaFields.

Yeah I attempted a modification of MetaField but that doesnt seem to be possible with the current arch.

Could you explain the larger context of what you are trying to do? I suspect that what you are looking for is covered be .apply(...), .transform(...) or .and_then(...).

It's a classic custom serialization situation, with set of functions, some that need to work on members and evaluate if they need to do something with the runtime value of that member depending on some properties of the type. Nothing special.

Do you mean to use to_view(object).apply(...) etc.? It might solve my problem, I wasnt aware that to_view's elements would provide access to the value too.

liuzicheng1987 commented 3 months ago

@Klaim it's in the README:


auto lisa = Person{.first_name = "Lisa", .last_name = "Simpson", .age = 8};

view.apply([](const auto& f) {
  // f is a an rfl::Field pointing to the original field.
  std::cout << f.name() << ": " << rfl::json::write(*f.value()) << std::endl;
});

.apply() allows you to iterate through the fields of a named tuple and then access the field names and values. .name() is a constexpr and can be evaluated at compile time.

A view is simply a named tuple with pointers to the original fields. It is meant for use cases like this. I also use it for the serialization and deserialization of structs, because it is very efficient.

To be fair, this is something that we added relatively recently. But I think this is what you are looking for.

Klaim commented 3 months ago

Yes I'll confirm tomorrow but I think I can use that. I'll close the issue for now and I'll reopen it if I find it's not enough.

I think some improvements could be done on the organisation and specificity of the documentation, I'll try to report some specific issues about that later.