| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- #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_;
- }
|