#include <iostream>
#include <tuple>
using namespace std;
template<
typename Callable,
typename Tuple,
size_t... Indexes
>
constexpr void tuple_for_each(Tuple&& t, Callable&& f, std::index_sequence<Indexes...>)
{
(f(std::get<Indexes>(t)), ...);
}
template<
typename Callable,
typename... Args,
template<typename...> typename Tuple,
typename Is = std::make_index_sequence<sizeof...(Args)>
>
constexpr void tuple_for_each(Tuple<Args...>&& t, Callable&& f)
{
tuple_for_each(t, f, Is{});
}
template<typename T>
struct ReflectionLayout
{
static constexpr auto GetLayout()
{
return std::make_tuple(
std::make_tuple(
"#Unknown", "Unknown"
)
);
}
};
template<typename T>
struct Reflection
{
static constexpr bool has_reflection_info = false;
static constexpr char const* name{ "Unknown" };
static constexpr auto layout() { return ReflectionLayout<T>::GetLayout(); }
static constexpr bool is_complex{ false };
};
#define REGISTER_REFLECTION_INFO(Class) \
template<> \
struct Reflection<Class> \
{ \
static constexpr bool has_reflection_info = true; \
static constexpr char const* name{ #Class }; \
static constexpr auto layout() { return ReflectionLayout<Class>::GetLayout(); } \
static constexpr bool is_complex{ true }; \
};
#define REGISTER_REFLECTION_LAYOUT(Class) \
template<> \
struct ReflectionLayout<Class> \
{ \
using Type = Class; \
static constexpr auto GetLayout() \
{ \
return std::make_tuple(
#define MEMBER(Name) std::make_tuple(#Name, &Type::Name)
#define END_REFLECTION_LAYOUT(Class) \
); \
} \
}; \
REGISTER_REFLECTION_INFO(Class)
struct namedValue
{
string name;
int x;
};
REGISTER_REFLECTION_LAYOUT(namedValue)
MEMBER(name),
MEMBER(x)
END_REFLECTION_LAYOUT(namedValue)
template<typename T>
void printInfo(T val)
{
tuple_for_each(Reflection<T>::layout(),[&](auto&& x) {
auto [name, ptr] = x;
cout << name << ": " << val.*ptr << endl;
});
}
int main() {
printInfo(namedValue{"numEggs", 37});
return 0;
}