Skip to content

Instantly share code, notes, and snippets.

@veryjos
Created February 11, 2018 20:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save veryjos/506c0933b9d8ce6fc0bb1f210d4fda88 to your computer and use it in GitHub Desktop.
Save veryjos/506c0933b9d8ce6fc0bb1f210d4fda88 to your computer and use it in GitHub Desktop.
#pragma once
#include <string>
#include <functional>
#include <unordered_map>
template <typename T>
struct AutoPropMeta {
static AutoPropMeta<T>* GetInstance() {
static bool first = true;
static AutoPropMeta<T> instance;
if (first) {
first = false;
T::InitAutoPropChain();
}
return &instance;
};
std::unordered_map<std::string, std::function<void(T*, int)>> setters;
};
template <int i>
struct AutoPropIndex {
static constexpr const int index = i;
};
template <typename T, int i, typename R>
static constexpr int NextValue() {
if constexpr (decltype(T::__meta_counter(AutoPropIndex<i>{}))::index == -1) {
return i;
} else {
return NextValue<T, i + 1, R>();
}
};
#define AUTOPROP_ENABLE(mytyyype) \
using MYTYPE = mytyyype;\
\
template <int i> \
static constexpr AutoPropIndex<-1> __meta_counter(AutoPropIndex<i>); \
\
static inline void InitAutoPropChain() { \
InitAutoPropChainRecurse<0>(); \
} \
\
template <int currentIndex> \
static inline void InitAutoPropChainRecurse() { \
if constexpr (HasProp(AutoPropIndex<currentIndex>{})) { \
InitProp(AutoPropIndex<currentIndex>{}); \
\
InitAutoPropChainRecurse<currentIndex + 1>(); \
} \
} \
\
static inline constexpr bool HasProp(...) { \
return false; \
} \
\
static inline void Set(MYTYPE& obj, const std::string& propertyName, int value) { \
auto meta = AutoPropMeta<MYTYPE>::GetInstance(); \
\
meta->setters[propertyName](&obj, value); \
}
#define CONCAT_(x,y) x##y
#define CONCAT(x,y) CONCAT_(x,y)
#define AUTOPROP(name) __AUTOPROP_IMPL(name, CONCAT(__meta_index_, name), __LINE__)
#define __AUTOPROP_IMPL(name, ident, line) \
static constexpr const int ident = NextValue<MYTYPE, 0, AutoPropIndex<line>>(); \
static constexpr AutoPropIndex<1> __meta_counter(AutoPropIndex<ident>); \
\
static inline constexpr bool HasProp(AutoPropIndex<ident>) { \
return true; \
}; \
\
static inline void InitProp(AutoPropIndex<ident>) { \
auto meta = AutoPropMeta<MYTYPE>::GetInstance(); \
\
meta->setters[#name] = [](MYTYPE* ptr, int value) { \
ptr->name = value; \
}; \
};
#pragma once
#include "AutoProp.hpp"
struct LayoutMeta {
AUTOPROP_ENABLE(LayoutMeta)
AUTOPROP(x)
int x;
AUTOPROP(y)
int y;
AUTOPROP(z)
int z;
};
#include "LayoutMeta.hpp"
int main(int argc, char** argv) {
printf("Size of LayoutMeta: %lu\n", sizeof(LayoutMeta));
LayoutMeta test;
test.x = 33;
printf("Before reflection: test.x = %d\n", test.x);
LayoutMeta::Set(test, "x", 44);
printf("After reflection: test.x = %d\n", test.x);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment