vkmEngine 1.0.0
A C++ game engine · vkmengine.com
Loading...
Searching...
No Matches
reflect.h
1#pragma once
2
3#include <cstddef>
4#include <string_view>
5#include <tuple>
6#include <type_traits>
7
8namespace Vkm::Engine::Reflect {
9
16template<typename T>
17inline constexpr bool DEPENDENT_FALSE = false;
18
24template<typename T, typename M>
25struct Field {
26 std::string_view name;
27 M T::* ptr;
28};
29
30// `Field{"position", &Transform::position}` deduces T=Transform, M=glm::vec3.
31template<typename T, typename M>
32Field(const char*, M T::*) -> Field<T, M>;
33
40template<typename T>
41struct Traits;
42
51template<typename T, typename Fn>
52constexpr void forEachField(T& obj, Fn&& fn) {
53 using Bare = std::remove_const_t<T>;
54 constexpr auto tup = Traits<Bare>::fields();
55 const auto visit = [&](auto&&... f) { ((fn(f.name, obj.*(f.ptr))), ...); };
56 std::apply(visit, tup);
57}
58
67constexpr const char* shortName(const char* qualified) {
68 const char* last = qualified;
69 for (const char* p = qualified; *p; ++p) {
70 if (p[0] == ':' && p[1] == ':') last = p + 2;
71 }
72 return last;
73}
74
81template<typename Enum>
82struct EnumNames;
83
91template<typename Enum>
92constexpr const char* enumName(Enum value) {
93 using Names = EnumNames<Enum>;
94 const auto index = static_cast<std::size_t>(value);
95 return index < Names::count ? Names::values[index] : Names::values[0];
96}
97
106template<typename Enum>
107bool enumFromNameChecked(std::string_view name, Enum& out) {
108 using Names = EnumNames<Enum>;
109 for (std::size_t i = 0; i < Names::count; ++i) {
110 if (name == Names::values[i]) {
111 out = static_cast<Enum>(i);
112 return true;
113 }
114 }
115 return false;
116}
117
123template<typename T, typename = void>
124inline constexpr bool IS_REFLECTED = false;
125
126template<typename T>
127inline constexpr bool IS_REFLECTED<T, std::void_t<decltype(Traits<T>::fields())>> = true;
128
132template<typename Enum, typename = void>
133inline constexpr bool HAS_ENUM_NAMES = false;
134
135template<typename Enum>
136inline constexpr bool HAS_ENUM_NAMES<Enum, std::void_t<decltype(EnumNames<Enum>::count)>> = true;
137
138} // namespace Vkm::Engine::Reflect
139
156#define VKM_REFLECT_BEGIN(Type) \
157 namespace Vkm::Engine::Reflect { \
158 template<> struct Traits<Type> { \
159 using vkm_reflect_self = Type; \
160 static constexpr const char* NAME = ::Vkm::Engine::Reflect::shortName(#Type); \
161 static constexpr auto fields() { \
162 return std::tuple_cat(
163
164#define VKM_F(name) \
165 std::make_tuple(::Vkm::Engine::Reflect::Field{#name, &vkm_reflect_self::name}),
166
167#define VKM_REFLECT_END() \
168 std::tuple<>() \
169 ); \
170 } \
171 }; \
172 }
173
183#define VKM_ENUM_NAMES(EnumType, ...) \
184 namespace Vkm::Engine::Reflect { \
185 template<> struct EnumNames<EnumType> { \
186 static constexpr const char* const values[] = { __VA_ARGS__ }; \
187 static constexpr std::size_t count = sizeof(values) / sizeof(values[0]); \
188 static_assert( \
189 count == static_cast<std::size_t>(EnumType::Count), \
190 #EnumType " names out of sync with its Count sentinel" \
191 ); \
192 }; \
193 }
Maps an enum to its value-ordered names.
Definition reflect.h:82
One (name, pointer-to-member) pair, the unit of compile-time field reflection.
Definition reflect.h:25
The reflection trait, specialised per type by VKM_REFLECT_BEGIN / VKM_F / VKM_REFLECT_END.
Definition reflect.h:41