reflection.h 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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 REFLECTION(expr) [=](Obj &obj, std::string name) { return Object(expr, std::move(name)); }
  11. #define CONST_REFLECTION(expr) [=](Obj const &obj, std::string name) { return Object(expr, std::move(name)); }
  12. namespace reflection {
  13. template <typename T>
  14. constexpr auto is_final_reflection =
  15. std::is_same_v<T, std::string> || std::is_fundamental_v<T>;
  16. template <typename Obj, typename> class Reflection {
  17. public:
  18. operator bool() const { return true; }
  19. static Getter<Obj> getter(std::string_view id) {
  20. if (auto it = const_members_.find(id); it != const_members_.end()) {
  21. return it->second;
  22. }
  23. throw std::out_of_range("no id in reflection");
  24. }
  25. static Accessor<Obj> accessor(std::string_view id) {
  26. if (auto it = members_.find(id); it != members_.end()) {
  27. return it->second;
  28. }
  29. throw std::out_of_range("no id in reflection");
  30. }
  31. template <typename T, typename V>
  32. Reflection &bind(std::string_view id, T (Obj::*get)() const, void (Obj::*set)(V)) {
  33. members_.emplace(id, REFLECTION(Proxy<T>(obj, get, set)));
  34. const_members_.emplace(id, CONST_REFLECTION((obj.*get)()));
  35. return *this;
  36. }
  37. template <typename T>
  38. Reflection &bind(std::string_view id, T Obj::*member) {
  39. members_.emplace(id, REFLECTION(obj.*member));
  40. const_members_.emplace(id, CONST_REFLECTION(obj.*member));
  41. return *this;
  42. }
  43. template <typename R, typename T>
  44. Reflection &bind(std::string_view id, T Obj::*member) {
  45. TypeConversion<R, T> convert;
  46. members_.emplace(id, CONST_REFLECTION(convert(obj.*member)));
  47. const_members_.emplace(id, CONST_REFLECTION(convert(obj.*member)));
  48. return *this;
  49. }
  50. private:
  51. static Cache<Accessor<Obj>> members_;
  52. static Cache<Getter<Obj>> const_members_;
  53. };
  54. template <typename T> class Reflection<T, std::enable_if_t<is_final_reflection<T>>> {
  55. public:
  56. static Getter<T> getter(std::string_view) { throw std::logic_error("unreflectable"); }
  57. static Accessor<T> accessor(std::string_view) { throw std::logic_error("unreflectable"); }
  58. };
  59. template <typename T> class Reflection<T*> {
  60. public:
  61. static auto getter(std::string_view id) {
  62. return [f = Reflection<T>::getter(id)](T const *ptr, std::string name) {
  63. return f(*ptr, std::move(name));
  64. };
  65. }
  66. static auto accessor(std::string_view id) {
  67. return [f = Reflection<T>::accessor(id)](T *ptr, std::string name) {
  68. return f(*ptr, std::move(name));
  69. };
  70. }
  71. };
  72. template <typename Obj, typename Void>
  73. Cache<Accessor<Obj>> Reflection<Obj, Void>::members_;
  74. template <typename Obj, typename Void>
  75. Cache<Getter<Obj>> Reflection<Obj, Void>::const_members_;
  76. }