Tatooine
reflection.h
Go to the documentation of this file.
1#ifndef TATOOINE_REFLECTION_H
2#define TATOOINE_REFLECTION_H
3//==============================================================================
4// Provides a facility to declare a type as "reflector" and apply a
5// reflection_visitor to it. The list of members is a compile-time data
6// structure, and there is no run-time overhead.
7//==============================================================================
9
10#include <concepts>
11#include <string_view>
12#include <type_traits>
13#include <utility>
14//==============================================================================
15namespace tatooine::reflection {
16//==============================================================================
17// Primary template which is specialized to register a type
18template <typename T>
19struct reflector {
20 static constexpr const bool value = false;
21};
22//==============================================================================
23template <typename T>
24struct is_reflectable_impl : std::integral_constant<bool, reflector<T>::value> {
25};
26// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
27template <typename T>
29// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
30template <typename T>
31concept reflectable = is_reflectable<std::decay_t<T>>;
32//==============================================================================
33// User-interface
34//==============================================================================
36template <typename T>
37constexpr auto num_members() -> std::size_t {
39}
40//------------------------------------------------------------------------------
41template <typename T>
42constexpr auto num_members(T &&) -> std::size_t {
43 return num_members<T>();
44}
45//------------------------------------------------------------------------------
47template <reflectable T, typename V>
48constexpr auto for_each(T &&t, V &&v) {
49 reflector<std::decay_t<T>>::for_each(std::forward<V>(v), std::forward<T>(t));
50}
51//------------------------------------------------------------------------------
52// Get value by index (like std::get for tuples)
53template <std::size_t idx, reflectable T>
54constexpr auto get(T &&t) {
56 std::integral_constant<std::size_t, idx>{}, std::forward<T>(t));
57}
58//------------------------------------------------------------------------------
59// Get name of field, by index
60template <std::size_t idx, reflectable T>
61constexpr auto name() {
63 std::integral_constant<std::size_t, idx>{});
64}
65//------------------------------------------------------------------------------
66template <std::size_t idx, typename T>
67constexpr auto name(T &&) -> decltype(name<idx, T>()) {
68 return name<idx, T>();
69}
70//------------------------------------------------------------------------------
71// Get name of structure
72template <reflectable T>
73constexpr auto name() {
75}
76//------------------------------------------------------------------------------
77template <reflectable T>
78constexpr auto name(T &&) {
79 return name<T>();
80}
81//------------------------------------------------------------------------------
82template <std::size_t I, typename T>
84 static_assert(is_reflectable<T>);
86 std::integral_constant<std::size_t, I>{}, std::declval<T>()));
87};
88//------------------------------------------------------------------------------
89template <std::size_t I, typename T>
91//------------------------------------------------------------------------------
92#define TATOOINE_REFLECTION_INSERT_MEMBER(MEMBER) \
93 MEMBER TATOOINE_PP_COMMA() MEMBER
94//------------------------------------------------------------------------------
95#define TATOOINE_REFLECTION_INSERT_GETTER(GETTER) \
96 GETTER TATOOINE_PP_COMMA() GETTER()
97//------------------------------------------------------------------------------
98#define TATOOINE_REFLECTION_INSERT_METHOD(NAME, ACCESSOR) \
99 NAME TATOOINE_PP_COMMA() ACCESSOR
100//------------------------------------------------------------------------------
101#define TATOOINE_REFLECTION_NAME(NAME, ACCESSOR) NAME
102//------------------------------------------------------------------------------
103#define TATOOINE_REFLECTION_ACCESSOR(NAME, ACCESSOR) ACCESSOR
104//------------------------------------------------------------------------------
105#define TATOOINE_REFLECTION_MEMBER_HELPER(NAME, ACCESSOR) v(#NAME, t.ACCESSOR);
106//------------------------------------------------------------------------------
107#define TATOOINE_REFLECTION_MAKE_ACCESSOR(NAME, ACCESSOR) \
108 template <reflectable Reflectable> \
109 static constexpr auto get( \
110 index_t<static_cast<std::size_t>(field_indices::NAME)>, Reflectable &&t) \
111 ->decltype(auto) { \
112 return t.ACCESSOR; \
113 }
114//------------------------------------------------------------------------------
115#define TATOOINE_REFLECTION_MAKE_NAME_GETTER(NAME, ACCESSOR) \
116 static constexpr auto name( \
117 index_t<static_cast<std::size_t>(field_indices::NAME)>) \
118 ->std::string_view { \
119 return #NAME; \
120 }
121//------------------------------------------------------------------------------
122#define TATOOINE_REFLECTION_MAKE_GETTERS(NAME, ACCESSOR) \
123 TATOOINE_REFLECTION_MAKE_ACCESSOR(NAME, ACCESSOR) \
124 TATOOINE_REFLECTION_MAKE_NAME_GETTER(NAME, ACCESSOR)
125//------------------------------------------------------------------------------
126#define TATOOINE_REFLECTION_FIELD_INDICES(...) \
127 enum class field_indices : std::size_t { __VA_ARGS__, count___ }; \
128//==============================================================================
130#define TATOOINE_MAKE_SIMPLE_TYPE_REFLECTABLE(TYPE, ...) \
131 TATOOINE_MAKE_ADT_REFLECTABLE( \
132 TYPE, TATOOINE_PP_MAP(TATOOINE_REFLECTION_INSERT_MEMBER, __VA_ARGS__))
133//------------------------------------------------------------------------------
134#define TATOOINE_MAKE_ADT_REFLECTABLE(TYPE, ...) \
135 template <> \
136 TATOOINE_MAKE_TEMPLATED_ADT_REFLECTABLE(TYPE, __VA_ARGS__)
137//------------------------------------------------------------------------------
138#define TATOOINE_MAKE_TEMPLATED_ADT_REFLECTABLE(TYPE, ...) \
139 struct reflector<TATOOINE_PP_PASS_ARGS(TYPE)> { \
140 template <std::size_t I> \
141 using index_t = std::integral_constant<std::size_t, I>; \
142 using reflected_type = TATOOINE_PP_PASS_ARGS(TYPE); \
143 static constexpr const bool value = true; \
144 \
145 TATOOINE_REFLECTION_FIELD_INDICES(TATOOINE_PP_ODDS(__VA_ARGS__)) \
146 static constexpr auto num_members() { \
147 return static_cast<std::size_t>(field_indices::count___); \
148 } \
149 static constexpr auto name() -> std::string_view { \
150 return TATOOINE_PP_TO_STRING(TYPE); \
151 } \
152 \
153 TATOOINE_PP_MAP2(TATOOINE_REFLECTION_MAKE_GETTERS, __VA_ARGS__) \
154 \
155 template <reflectable Reflectable, typename V> \
156 constexpr static auto for_each([[maybe_unused]] V && v, \
157 [[maybe_unused]] Reflectable &&t) -> void { \
158 for_each(std::forward<V>(v), std::forward<Reflectable>(t), \
159 std::make_index_sequence<num_members()>{}); \
160 } \
161 template <reflectable Reflectable, typename V, std::size_t... Is> \
162 constexpr static auto for_each([[maybe_unused]] V && v, \
163 [[maybe_unused]] Reflectable &&t, \
164 std::index_sequence<Is...>) -> void { \
165 (v(name(index_t<Is>{}), get(index_t<Is>{}, t)), ...); \
166 } \
167 };
168//==============================================================================
169} // namespace tatooine::reflection
170//==============================================================================
171#endif
Definition: reflection.h:31
Definition: linspace.h:172
constexpr auto for_each(T &&t, V &&v)
Iterate over each registered member.
Definition: reflection.h:48
constexpr auto num_members() -> std::size_t
Return number of fields in a reflector struct.
Definition: reflection.h:37
static constexpr auto is_reflectable
Definition: reflection.h:28
typename get_type_impl< I, T >::type get_type
Definition: reflection.h:90
constexpr auto name()
Definition: reflection.h:61
typename get_impl< Container, I >::type get
Definition: get.h:11
Definition: reflection.h:83
decltype(reflector< std::decay_t< T > >::get(std::integral_constant< std::size_t, I >{}, std::declval< T >())) type
Definition: reflection.h:86
Definition: reflection.h:19
static constexpr const bool value
Definition: reflection.h:20