reflect.hpp 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. #pragma once
  2. #include <string>
  3. #include <unordered_map>
  4. template <typename Object>
  5. class reflection {
  6. private:
  7. template <typename T> using Field = T Object::*;
  8. template <typename K, typename V> using map = std::unordered_map<K, V>;
  9. private:
  10. template <typename T> static map<std::string, Field<T>> s_reflector;
  11. static map<std::ptrdiff_t, std::string> s_fieldname;
  12. private:
  13. template <typename T>
  14. static std::ptrdiff_t offset(Field<T> field) {
  15. return std::ptrdiff_t(&(reinterpret_cast<Object const*>(NULL)->*field));
  16. }
  17. static std::string_view name(std::ptrdiff_t offset) {
  18. auto it = s_fieldname.find(offset);
  19. if (it == s_fieldname.end()) { return ""; }
  20. return it->second;
  21. }
  22. public:
  23. reflection();
  24. template <typename T>
  25. static bool exists(std::string const & name) {
  26. return s_reflector<T>.count(name);
  27. }
  28. template <typename T>
  29. static Field<T> get_pointer(std::string const & name) {
  30. auto it = s_reflector<T>.find(name);
  31. if (it == s_reflector<T>.end()) { return nullptr; }
  32. return it->second;
  33. }
  34. template <typename T>
  35. static std::string_view name(Object const * ptr, T const & data) {
  36. return name(std::ptrdiff_t(&data) - std::ptrdiff_t(ptr));
  37. }
  38. template <typename T>
  39. static std::string_view name(Object const & obj, T const & data) {
  40. return name(&obj, data);
  41. }
  42. template <typename T>
  43. static std::string_view name(Field<T> field) {
  44. return name(offset(field));
  45. }
  46. template <typename T>
  47. static void bind(Field<T> field, std::string const & name,
  48. std::string const & /*discard*/ = "") {
  49. s_fieldname.emplace(offset(field), name);
  50. s_reflector<T>.emplace(name, field);
  51. }
  52. };
  53. #define REFLECT_MEMBER_PP_IMPL2(type, field, ...) \
  54. bind(&type::field, ##__VA_ARGS__, #field)
  55. #define REFLECT_MEMBER_PP_IMPL(type, field, ...) \
  56. REFLECT_MEMBER_PP_IMPL2(type, field, ##__VA_ARGS__)
  57. #define UNWRAP(...) __VA_ARGS__
  58. #define REFLECT_MEMBER_PP2(data, elem) REFLECT_MEMBER_PP_IMPL(data, UNWRAP elem)
  59. #define REFLECT_MEMBER_PP(r, data, elem) REFLECT_MEMBER_PP2(data, elem);
  60. #include <boost/preprocessor/variadic/to_seq.hpp>
  61. #include <boost/preprocessor/seq/for_each.hpp>
  62. #define CONCAT2(A, B) A##B
  63. #define CONCAT(A, B) CONCAT2(A, B)
  64. #define CREATE_REFLECTION(type, ...) \
  65. template <> reflection<type>::reflection() { \
  66. BOOST_PP_SEQ_FOR_EACH(REFLECT_MEMBER_PP, type, \
  67. BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)) \
  68. } \
  69. static reflection<type> CONCAT(reflector_, __LINE__) {}
  70. template <typename Object> template <typename T>
  71. std::unordered_map<std::string, T Object::*> reflection<Object>::s_reflector;
  72. template <typename Object>
  73. std::unordered_map<std::ptrdiff_t, std::string> reflection<Object>::s_fieldname;