Here's one way to solve the serialization problem in c++20, using a json library:
#include <functional>
#include <unordered_map>
#include "json.hpp"
namespace nlm = nlohmann;
class properties
{
struct property_info
{
std::function<void(nlm::json const&)> deserializor;
std::function<nlm::json()> serializor;
};
std::unordered_map<std::string_view, property_info> reg_;
public:
//
nlm::json state() const;
void state(nlm::json const&);
//
template <typename U, typename ...A>
auto register_property(std::string_view const& k, U& v, A&& ...a)
{
static_assert(!(sizeof...(a) % 2));
static_assert(!(std::is_const_v<U>));
reg_.try_emplace(k,
[&v](nlm::json const& j){v = j.get<U>();},
[&v]{return nlm::json(v);}
);
if constexpr (sizeof...(a))
{
register_property(std::forward<A>(a)...);
}
return [this](auto&& ...a)
{
return register_property(std::forward<decltype(a)>(a)...);
};
}
auto get(std::string_view const& k)
{
return reg_.find(k)->second.serializor();
}
template <typename U>
void set(std::string_view const& k, U&& v)
{
reg_.find(k)->second.deserializor(std::forward<U>(v));
}
};
nlm::json properties::state() const
{
nlm::json r(nlm::json::object());
for (auto i(reg_.cbegin()), cend(reg_.cend()); cend != i; i = std::next(i))
{
r.emplace(i->first, i->second.serializor());
}
return r;
}
void properties::state(nlm::json const& e)
{
assert(e.is_object());
auto const cend(reg_.cend());
for (auto i(e.cbegin()), ecend(e.cend()); ecend != i; i = std::next(i))
{
auto& key(i.key());
if (auto const j(std::as_const(reg_).find(key)); cend != j)
{
j->second.deserializor(i.value());
}
}
}
Example:
int main()
{
struct S: properties
{
bool b{};
int i{};
S()
{
register_property("b", b)("i", i);
}
} s;
s.set("b", true);
s.set("i", 11.1);
std::cout << s.get("b") << std::endl;
std::cout << s.state() << std::endl;
}
2 functors for (de)serializing are generated for each registered property. If state is requested or set, these are executed accordingly. Obvious improvements are certain checks, getters/setters, instead of references. I think this is a nice quick solution for simple cases.