Skip to content

Instantly share code, notes, and snippets.

@eliasdaler
Created September 26, 2017 09:31
Show Gist options
  • Save eliasdaler/213d42051958ae21185adbc7edbff915 to your computer and use it in GitHub Desktop.
Save eliasdaler/213d42051958ae21185adbc7edbff915 to your computer and use it in GitHub Desktop.
Simple meta info class for this article: https://eliasdaler.github.io/meta-stuff
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <json.hpp>
using json = nlohmann::json;
template <typename Class>
class IMember {
public:
virtual ~IMember() = default;
virtual void fromJson(Class& obj, const json& j) const = 0;
virtual json toJson(const Class& obj) const = 0;
};
template <typename Class, typename T>
class Member : public IMember<Class> {
public:
Member(T Class::* ptr) : ptr(ptr) {}
void fromJson(Class& obj, const json& j) const override
{
obj.*ptr = j;
}
json toJson(const Class& obj) const override
{
return json(obj.*ptr);
}
private:
T Class::* ptr;
};
namespace ImGui
{
void Input(int anim);
}
template <typename Class>
class ClassMetaInfo {
public:
static void serialize(Class& obj, const json& j)
{
for (const auto& pair : members) {
const auto& memberName = pair.first;
const auto& memberPtr = pair.second;
memberPtr->fromJson(obj, j[memberName]);
}
}
static json deserialize(const Class& obj)
{
json j;
for (const auto& pair : members) {
const auto& memberName = pair.first;
const auto& memberPtr = pair.second;
j[memberName] = memberPtr->toJson(obj);
}
return j;
}
template <typename T>
static void registerMember(const char* name, T Class::* ptr)
{
members.emplace(name, std::make_unique<Member<Class, T>>(ptr));
}
using MemberPtrType = std::unique_ptr<IMember<Class>>;
using MemberMapType = std::unordered_map<std::string, MemberPtrType>;
private:
static MemberMapType members;
};
template <typename Class>
typename ClassMetaInfo<Class>::MemberMapType ClassMetaInfo<Class>::members;
struct Person {
std::string name;
int age;
static void registerClass()
{
ClassMetaInfo<Person>::registerMember("name", &Person::name);
ClassMetaInfo<Person>::registerMember("age", &Person::age);
}
};
int main()
{
std::tuple<Member<Person, std::string>, Member<Person, int>> members;
Person::registerClass();
Person p{ "John", 30 };
json j = ClassMetaInfo<Person>::deserialize(p);
std::cout << std::setw(4) << j << std::endl;
Person p2;
ClassMetaInfo<Person>::serialize(p2, j);
std::cout << "Name = " << p2.name << ", age = " << p2.age << "\n";
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment