| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- #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 BIND_F(expr) [](auto &_) -> decltype(auto) { return expr; }
- #define REFLECTION_F(expr) \
- [=](Obj & obj, std::string name) { return Object(expr, std::move(name)); }
- #define CONST_REFLECTION_F(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> ||
- std::is_enum_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 R, typename I>
- Reflection & bind(std::string_view id, R (Obj::*get)() const,
- void (Obj::*set)(I)) {
- using V = std::decay_t<R>;
- members_.emplace(id, REFLECTION_F(Proxy<V>(obj, get, set)));
- const_members_.emplace(id, CONST_REFLECTION_F((obj.*get)()));
- return *this;
- }
-
- template <typename R, typename I>
- Reflection & bind(std::string_view id, R Obj::*member,
- void (Obj::*set)(I)) {
- using V = std::decay_t<R>;
- members_.emplace(id, REFLECTION_F(Proxy<V>(obj, member, set)));
- const_members_.emplace(id, CONST_REFLECTION_F(obj.*member));
- return *this;
- }
- template <typename R>
- Reflection & bind(std::string_view id, R (Obj::*get)() const,
- std::decay_t<R> & (Obj::*acc)()) {
- members_.emplace(id, REFLECTION_F((obj.*acc)()));
- const_members_.emplace(id, CONST_REFLECTION_F((obj.*get)()));
- return *this;
- }
- template <typename T>
- Reflection & bind(std::string_view id, T (Obj::*get)() const) {
- const_members_.emplace(id, CONST_REFLECTION_F((obj.*get)()));
- return *this;
- }
- template <typename T> Reflection & bind(std::string_view id, T Obj::*member) {
- members_.emplace(id, REFLECTION_F(obj.*member));
- const_members_.emplace(id, CONST_REFLECTION_F(obj.*member));
- return *this;
- }
- template <typename Get, typename Set>
- Reflection & bind(std::string_view id, Get get, Set set) {
- using V = std::decay_t<std::invoke_result_t<Get, Obj &>>;
- members_.emplace(id, REFLECTION_F(Proxy<V>(obj, get, set)));
- const_members_.emplace(id, CONST_REFLECTION_F(get(obj)));
- return *this;
- }
- template <typename Get> Reflection & bind(std::string_view id, Get get) {
- if constexpr (!std::is_const_v<std::invoke_result_t<Get, Obj &>>) {
- members_.emplace(id, REFLECTION_F(get(obj)));
- } else {
- members_.emplace(id, CONST_REFLECTION_F(get(obj)));
- }
- const_members_.emplace(id, CONST_REFLECTION_F(get(obj)));
- 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_;
- }
- #undef REFLECTION_F
- #undef CONST_REFLECTION_F
|