| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- #pragma once
- #include <string>
- #include <unordered_map>
- template <typename Object>
- class reflection {
- private:
- template <typename T> using Field = T Object::*;
- template <typename K, typename V> using map = std::unordered_map<K, V>;
-
- private:
- template <typename T> static map<std::string, Field<T>> s_reflector;
- static map<std::ptrdiff_t, std::string> s_fieldname;
-
- private:
- template <typename T>
- static std::ptrdiff_t offset(Field<T> field) {
- return std::ptrdiff_t(&(reinterpret_cast<Object const*>(NULL)->*field));
- }
-
- static std::string_view name(std::ptrdiff_t offset) {
- auto it = s_fieldname.find(offset);
- if (it == s_fieldname.end()) { return ""; }
- return it->second;
- }
- public:
- reflection();
- template <typename T>
- static bool exists(std::string const & name) {
- return s_reflector<T>.count(name);
- }
- template <typename T>
- static Field<T> get_pointer(std::string const & name) {
- auto it = s_reflector<T>.find(name);
- if (it == s_reflector<T>.end()) { return nullptr; }
- return it->second;
- }
-
- template <typename T>
- static std::string_view name(Object const * ptr, T const & data) {
- return name(std::ptrdiff_t(&data) - std::ptrdiff_t(ptr));
- }
-
- template <typename T>
- static std::string_view name(Object const & obj, T const & data) {
- return name(&obj, data);
- }
-
- template <typename T>
- static std::string_view name(Field<T> field) {
- return name(offset(field));
- }
- template <typename T>
- static void bind(Field<T> field, std::string const & name,
- std::string const & /*discard*/ = "") {
- s_fieldname.emplace(offset(field), name);
- s_reflector<T>.emplace(name, field);
- }
- };
- #define REFLECT_MEMBER_PP_IMPL2(type, field, ...) \
- bind(&type::field, ##__VA_ARGS__, #field)
- #define REFLECT_MEMBER_PP_IMPL(type, field, ...) \
- REFLECT_MEMBER_PP_IMPL2(type, field, ##__VA_ARGS__)
- #define UNWRAP(...) __VA_ARGS__
- #define REFLECT_MEMBER_PP2(data, elem) REFLECT_MEMBER_PP_IMPL(data, UNWRAP elem)
- #define REFLECT_MEMBER_PP(r, data, elem) REFLECT_MEMBER_PP2(data, elem);
- #include <boost/preprocessor/variadic/to_seq.hpp>
- #include <boost/preprocessor/seq/for_each.hpp>
- #define CONCAT2(A, B) A##B
- #define CONCAT(A, B) CONCAT2(A, B)
- #define CREATE_REFLECTION(type, ...) \
- template <> reflection<type>::reflection() { \
- BOOST_PP_SEQ_FOR_EACH(REFLECT_MEMBER_PP, type, \
- BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
- } \
- static reflection<type> CONCAT(reflector_, __LINE__) {}
- template <typename Object> template <typename T>
- std::unordered_map<std::string, T Object::*> reflection<Object>::s_reflector;
- template <typename Object>
- std::unordered_map<std::ptrdiff_t, std::string> reflection<Object>::s_fieldname;
|