#include <map>
#include <tuple>
#include <string>
#include <typeinfo>
#define REGISTER_ELEM( ELEM ) \
{ Reflectable* p = this; } \
register_element( #ELEM, typeid(ELEM).name(), &ELEM )
struct Reflectable {
public:
class Caster {
public:
Caster(void* ptr) : m_ptr(ptr) {}
Caster() {}
template<typename T> operator T&() {
return *reinterpret_cast<T*>(m_ptr);
}
private:
void* m_ptr;
};
Caster& get(const std::string key) {
return std::get<1>(m_elements.at(key));
}
std::string type(const std::string key) {
return std::get<0>(m_elements.at(key));
}
protected:
void register_element(const std::string key, const std::string type_name, void* ptr) {
m_elements[key] = std::make_tuple(type_name, Caster(ptr));
}
private:
std::map<const std::string, std::tuple<std::string, Caster>> m_elements;
};
// main.cpp
#include <iostream>
struct Test : Reflectable {
int a = 123;
double b = 256;
Test() {
REGISTER_ELEM(a);
REGISTER_ELEM(b);
}
};
int main(void) {
Test test;
int a = test.get("a");
double b = test.get("b");
std::cout << "a is " << a << std::endl;
std::cout << "b is " << b << std::endl;
}
CiNpbmNsdWRlIDxtYXA+CiNpbmNsdWRlIDx0dXBsZT4KI2luY2x1ZGUgPHN0cmluZz4KI2luY2x1ZGUgPHR5cGVpbmZvPgoKI2RlZmluZSBSRUdJU1RFUl9FTEVNKCBFTEVNICkgICAgXAogICAgeyBSZWZsZWN0YWJsZSogcCA9IHRoaXM7IH0gICBcCiAgICByZWdpc3Rlcl9lbGVtZW50KCAjRUxFTSwgdHlwZWlkKEVMRU0pLm5hbWUoKSwgJkVMRU0gKQoKCnN0cnVjdCBSZWZsZWN0YWJsZSB7CgkKcHVibGljOgoJY2xhc3MgQ2FzdGVyIHsKCXB1YmxpYzoKCQlDYXN0ZXIodm9pZCogcHRyKSA6IG1fcHRyKHB0cikge30KCQlDYXN0ZXIoKSB7fQoKCQl0ZW1wbGF0ZTx0eXBlbmFtZSBUPiBvcGVyYXRvciBUJigpIHsKCQkJcmV0dXJuICpyZWludGVycHJldF9jYXN0PFQqPihtX3B0cik7CgkJfQoKCXByaXZhdGU6CgkJdm9pZCogbV9wdHI7CgoJfTsKCglDYXN0ZXImIGdldChjb25zdCBzdGQ6OnN0cmluZyBrZXkpIHsKCQlyZXR1cm4gc3RkOjpnZXQ8MT4obV9lbGVtZW50cy5hdChrZXkpKTsKCX0KCglzdGQ6OnN0cmluZyB0eXBlKGNvbnN0IHN0ZDo6c3RyaW5nIGtleSkgewoJCXJldHVybiBzdGQ6OmdldDwwPihtX2VsZW1lbnRzLmF0KGtleSkpOwoJfQoJCnByb3RlY3RlZDoKCXZvaWQgcmVnaXN0ZXJfZWxlbWVudChjb25zdCBzdGQ6OnN0cmluZyBrZXksIGNvbnN0IHN0ZDo6c3RyaW5nIHR5cGVfbmFtZSwgdm9pZCogcHRyKSB7CgkJCW1fZWxlbWVudHNba2V5XSA9IHN0ZDo6bWFrZV90dXBsZSh0eXBlX25hbWUsIENhc3RlcihwdHIpKTsKCX0KCnByaXZhdGU6CgkKCXN0ZDo6bWFwPGNvbnN0IHN0ZDo6c3RyaW5nLCBzdGQ6OnR1cGxlPHN0ZDo6c3RyaW5nLCBDYXN0ZXI+PiBtX2VsZW1lbnRzOwp9OwoKCi8vIG1haW4uY3BwCgojaW5jbHVkZSA8aW9zdHJlYW0+CgpzdHJ1Y3QgVGVzdCA6IFJlZmxlY3RhYmxlIHsKCWludCBhID0gMTIzOwoJZG91YmxlIGIgPSAyNTY7CgoJVGVzdCgpIHsKCQlSRUdJU1RFUl9FTEVNKGEpOwoJCVJFR0lTVEVSX0VMRU0oYik7Cgl9Cn07CgppbnQgbWFpbih2b2lkKSB7CglUZXN0IHRlc3Q7CgkKCWludCBhID0gdGVzdC5nZXQoImEiKTsKCWRvdWJsZSBiID0gdGVzdC5nZXQoImIiKTsKCXN0ZDo6Y291dCA8PCAiYSBpcyAiIDw8IGEgPDwgc3RkOjplbmRsOwoJc3RkOjpjb3V0IDw8ICJiIGlzICIgPDwgYiA8PCBzdGQ6OmVuZGw7Cn0KCg==