-
Notifications
You must be signed in to change notification settings - Fork 0
/
reflect.h
112 lines (90 loc) · 2.18 KB
/
reflect.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#include <typeinfo>
using std::type_info;
template< typename... Args >
std::string string_sprintf(const char* format, Args... args)
{
int length = std::snprintf(nullptr, 0, format, args...);
assert(length >= 0);
char* buf = new char[length + 1];
std::snprintf(buf, length + 1, format, args...);
std::string str(buf);
delete[] buf;
return std::move(str);
}
template<typename base_t>
static auto GetFunctionBaseType(void(base_t::*)()) -> base_t;
#define GENERATE_BODY() \
public: \
static Class* StaticClass() { static ClassOf<this_t> _class; return &_class; } \
virtual Class* GetClass() { static ClassOf<this_t> _class; return &_class; } \
private: \
template<typename T> void GetBaseType() {} \
typedef decltype(GetFunctionBaseType(&GetBaseType<void>)) this_t; \
class Class
{
template <class T>
friend class ClassOf;
private:
virtual const type_info& get_type_info() const = 0;
public:
virtual size_t size() const = 0;
virtual const char* name() const = 0;
virtual size_t hash() const = 0;
bool operator==(const Class& _class) const
{
return get_type_info() == _class.get_type_info();
}
};
template <class T>
class ClassOf : public Class
{
private:
virtual const type_info& get_type_info() const override
{
return typeid(T);
}
public:
ClassOf() {}
ClassOf(const Class& _class)
{
if (typeid(T) != _class.get_type_info())
{
auto const& message = string_sprintf("'%s' is not base of '%s'", typeid(T).name(), _class.get_type_info().name());
throw std::bad_cast::__construct_from_string_literal(message.c_str());
}
}
virtual size_t size() const override
{
return sizeof(T);
}
virtual const char* name() const override
{
return typeid(T).name();
}
virtual size_t hash() const override
{
return typeid(T).hash_code();
}
};
class Object
{
GENERATE_BODY();
};
class Field : public Object
{
GENERATE_BODY();
private:
size_t offset;
public:
Field(const size_t& offset) : offset(offset) {}
template <typename T>
T get(void* object)
{
return *reinterpret_cast<T*>(reinterpret_cast<char*>(object) + offset);
}
template <typename T>
void set(void* object, const T& value)
{
*reinterpret_cast<T*>(reinterpret_cast<char*>(object) + offset) = value;
}
};