| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- #pragma once
- #include <functional>
- #include <stdexcept>
- #include <string>
- #include <type_traits>
- #include <utility>
- #include "reflection/forward.h"
- #include "reflection/object.h"
- #include "reflection/proxy.h"
- #define REFLECTION(expr) [=](Obj &obj, std::string name) { return Object(expr, std::move(name)); }
- #define CONST_REFLECTION(expr) [=](Obj const &obj, std::string name) { return Object(expr, std::move(name)); }
- namespace reflection {
- template <typename T>
- constexpr auto is_final_reflection =
- std::is_same_v<T, std::string> || std::is_fundamental_v<T>;
- template <typename Obj, typename> class Reflection {
- public:
- operator bool() const { return true; }
-
- static Getter<Obj> getter(std::string_view id) {
- if (auto it = const_members_.find(id); it != const_members_.end()) {
- return it->second;
- }
- throw std::out_of_range("no id in reflection");
- }
- static Accessor<Obj> accessor(std::string_view id) {
- if (auto it = members_.find(id); it != members_.end()) {
- return it->second;
- }
- throw std::out_of_range("no id in reflection");
- }
- template <typename T, typename V>
- Reflection &bind(std::string_view id, T (Obj::*get)() const, void (Obj::*set)(V)) {
- members_.emplace(id, REFLECTION(Proxy<T>(obj, get, set)));
- const_members_.emplace(id, CONST_REFLECTION((obj.*get)()));
- return *this;
- }
- template <typename T>
- Reflection &bind(std::string_view id, T Obj::*member) {
- members_.emplace(id, REFLECTION(obj.*member));
- const_members_.emplace(id, CONST_REFLECTION(obj.*member));
- return *this;
- }
- template <typename R, typename T>
- Reflection &bind(std::string_view id, T Obj::*member) {
- TypeConversion<R, T> convert;
- members_.emplace(id, CONST_REFLECTION(convert(obj.*member)));
- const_members_.emplace(id, CONST_REFLECTION(convert(obj.*member)));
- return *this;
- }
- private:
- static Cache<Accessor<Obj>> members_;
- static Cache<Getter<Obj>> const_members_;
- };
- template <typename T> class Reflection<T, std::enable_if_t<is_final_reflection<T>>> {
- public:
- static Getter<T> getter(std::string_view) { throw std::logic_error("unreflectable"); }
- static Accessor<T> accessor(std::string_view) { throw std::logic_error("unreflectable"); }
- };
- template <typename T> class Reflection<T*> {
- public:
- static auto getter(std::string_view id) {
- return [f = Reflection<T>::getter(id)](T const *ptr, std::string name) {
- return f(*ptr, std::move(name));
- };
- }
- static auto accessor(std::string_view id) {
- return [f = Reflection<T>::accessor(id)](T *ptr, std::string name) {
- return f(*ptr, std::move(name));
- };
- }
- };
- template <typename Obj, typename Void>
- Cache<Accessor<Obj>> Reflection<Obj, Void>::members_;
- template <typename Obj, typename Void>
- Cache<Getter<Obj>> Reflection<Obj, Void>::const_members_;
- }
|