reflection.h 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #pragma once
  2. #include <functional>
  3. #include <stdexcept>
  4. #include <string>
  5. #include <type_traits>
  6. #include <utility>
  7. #include "reflection/forward.h"
  8. #include "reflection/object.h"
  9. #include "reflection/proxy.h"
  10. #define BIND_F(expr) [](auto &_) -> decltype(auto) { return expr; }
  11. #define REFLECTION_F(expr) \
  12. [=](Obj & obj, std::string name) { return Object(expr, std::move(name)); }
  13. #define CONST_REFLECTION_F(expr) \
  14. [=](Obj const & obj, std::string name) { \
  15. return Object(expr, std::move(name)); \
  16. }
  17. namespace reflection {
  18. template <typename T>
  19. constexpr auto is_final_reflection =
  20. std::is_same_v<T, std::string> || std::is_fundamental_v<T> ||
  21. std::is_enum_v<T>;
  22. template <typename Obj, typename> class Reflection {
  23. public:
  24. operator bool() const { return true; }
  25. static Getter<Obj> getter(std::string_view id) {
  26. if (auto it = const_members_.find(id); it != const_members_.end()) {
  27. return it->second;
  28. }
  29. throw std::out_of_range("no id in reflection");
  30. }
  31. static Accessor<Obj> accessor(std::string_view id) {
  32. if (auto it = members_.find(id); it != members_.end()) {
  33. return it->second;
  34. }
  35. throw std::out_of_range("no id in reflection");
  36. }
  37. template <typename R, typename I>
  38. Reflection & bind(std::string_view id, R (Obj::*get)() const,
  39. void (Obj::*set)(I)) {
  40. using V = std::decay_t<R>;
  41. members_.emplace(id, REFLECTION_F(Proxy<V>(obj, get, set)));
  42. const_members_.emplace(id, CONST_REFLECTION_F((obj.*get)()));
  43. return *this;
  44. }
  45. template <typename R, typename I>
  46. Reflection & bind(std::string_view id, R Obj::*member,
  47. void (Obj::*set)(I)) {
  48. using V = std::decay_t<R>;
  49. members_.emplace(id, REFLECTION_F(Proxy<V>(obj, member, set)));
  50. const_members_.emplace(id, CONST_REFLECTION_F(obj.*member));
  51. return *this;
  52. }
  53. template <typename R>
  54. Reflection & bind(std::string_view id, R (Obj::*get)() const,
  55. std::decay_t<R> & (Obj::*acc)()) {
  56. members_.emplace(id, REFLECTION_F((obj.*acc)()));
  57. const_members_.emplace(id, CONST_REFLECTION_F((obj.*get)()));
  58. return *this;
  59. }
  60. template <typename T>
  61. Reflection & bind(std::string_view id, T (Obj::*get)() const) {
  62. const_members_.emplace(id, CONST_REFLECTION_F((obj.*get)()));
  63. return *this;
  64. }
  65. template <typename T> Reflection & bind(std::string_view id, T Obj::*member) {
  66. members_.emplace(id, REFLECTION_F(obj.*member));
  67. const_members_.emplace(id, CONST_REFLECTION_F(obj.*member));
  68. return *this;
  69. }
  70. template <typename Get, typename Set>
  71. Reflection & bind(std::string_view id, Get get, Set set) {
  72. using V = std::decay_t<std::invoke_result_t<Get, Obj &>>;
  73. members_.emplace(id, REFLECTION_F(Proxy<V>(obj, get, set)));
  74. const_members_.emplace(id, CONST_REFLECTION_F(get(obj)));
  75. return *this;
  76. }
  77. template <typename Get> Reflection & bind(std::string_view id, Get get) {
  78. if constexpr (!std::is_const_v<std::invoke_result_t<Get, Obj &>>) {
  79. members_.emplace(id, REFLECTION_F(get(obj)));
  80. } else {
  81. members_.emplace(id, CONST_REFLECTION_F(get(obj)));
  82. }
  83. const_members_.emplace(id, CONST_REFLECTION_F(get(obj)));
  84. return *this;
  85. }
  86. private:
  87. static Cache<Accessor<Obj>> members_;
  88. static Cache<Getter<Obj>> const_members_;
  89. };
  90. template <typename T>
  91. class Reflection<T, std::enable_if_t<is_final_reflection<T>>> {
  92. public:
  93. static Getter<T> getter(std::string_view) {
  94. throw std::logic_error("unreflectable");
  95. }
  96. static Accessor<T> accessor(std::string_view) {
  97. throw std::logic_error("unreflectable");
  98. }
  99. };
  100. template <typename T> class Reflection<T *> {
  101. public:
  102. static auto getter(std::string_view id) {
  103. return [f = Reflection<T>::getter(id)](T const * ptr, std::string name) {
  104. return f(*ptr, std::move(name));
  105. };
  106. }
  107. static auto accessor(std::string_view id) {
  108. return [f = Reflection<T>::accessor(id)](T * ptr, std::string name) {
  109. return f(*ptr, std::move(name));
  110. };
  111. }
  112. };
  113. template <typename Obj, typename Void>
  114. Cache<Accessor<Obj>> Reflection<Obj, Void>::members_;
  115. template <typename Obj, typename Void>
  116. Cache<Getter<Obj>> Reflection<Obj, Void>::const_members_;
  117. }
  118. #undef REFLECTION_F
  119. #undef CONST_REFLECTION_F