-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.cpp
More file actions
184 lines (164 loc) · 5.93 KB
/
main.cpp
File metadata and controls
184 lines (164 loc) · 5.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include <algorithm>
#include <meta>
#include <print>
#include <ranges>
#include <string>
#include <string_view>
#include <type_traits>
template <typename T>
concept Reflectable = std::is_class_v<T> && std::is_aggregate_v<T>;
inline constexpr struct NoReflect {
} noReflect;
inline constexpr struct Printed {
} printed;
template <typename T>
consteval int CountPrintedMembers()
requires std::is_class_v<T>
{
auto ctx{std::meta::access_context::current()};
auto members{nonstatic_data_members_of(^^T, ctx)};
return std::ranges::count_if(members, [](std::meta::info m) {
return std::ranges::any_of(annotations_of(m), [](std::meta::info a) {
return type_of(a) == ^^Printed;
});
});
}
template <typename T>
requires(CountPrintedMembers<T>() > 0)
struct std::formatter<T> {
static_assert(
(CountPrintedMembers<T>() == 1),
identifier_of(^^T) +
std::string(" can only have exactly one [[=printed]] member. "
"Found multiple [[=printed]] annotations in this type."));
constexpr auto parse(std::format_parse_context &ctx) { return ctx.begin(); }
auto format(const T &obj, std::format_context &ctx) const {
constexpr auto printed_member = []() consteval -> auto {
auto ctx{std::meta::access_context::current()};
auto members{nonstatic_data_members_of(^^T, ctx)};
return *std::ranges::find_if(members, [](meta::info m) {
return std::ranges::any_of(annotations_of(m), [](meta::info a) {
return type_of(a) == ^^Printed;
});
});
}();
using MemberType = typename[:meta::type_of(printed_member):];
auto printedValue = obj.[:printed_member:];
return std::formatter<MemberType>{}.format(printedValue, ctx);
}
};
struct PrintableStruct {
[[= printed]] std::string name{"hello"};
int id{};
};
struct StrictInt {
explicit StrictInt(int v) : value(v) {}
[[= printed]] int value{};
PrintableStruct ps{};
};
template <typename T>
concept IsInt = std::is_same_v<T, int>;
template <typename T> constexpr void InspectType(T &obj) {
constexpr auto ctx{std::meta::access_context::current()};
constexpr auto allMembers{
define_static_array(nonstatic_data_members_of(^^T, ctx))};
constexpr auto members{std::define_static_array(
allMembers | std::views::filter([](std::meta::info m) {
return std::ranges::none_of(annotations_of(m),
[](std::meta::info annot) {
return type_of(annot) == ^^NoReflect;
});
}))};
template for (constexpr std::meta::info m : members) {
constexpr auto name{identifier_of(m)};
constexpr auto typeStr{display_string_of(type_of(m))};
using MemberType = typename[:type_of(m):];
if constexpr (Reflectable<MemberType>) {
std::println(" {}: {}", name, typeStr);
InspectType(obj.[:m:]);
} else if constexpr (std::formattable<MemberType, char>) {
std::println(" {}: {} = {}", name, typeStr, obj.[:m:]);
}
}
}
template <typename T> constexpr void ModifyFields(T &obj) {
constexpr auto ctx{std::meta::access_context::current()};
constexpr auto members{
define_static_array(nonstatic_data_members_of(^^T, ctx))};
template for (constexpr std::meta::info m : members) {
constexpr auto name{identifier_of(m)};
using MemberType = decltype(obj.[:m:]);
if constexpr (name == std::string_view("d")) {
std::println(" {} before: {}", name, obj.[:m:]);
obj.[:m:] = 999;
std::println(" {} before: {}", name, obj.[:m:]);
} else if constexpr (std::is_same_v<MemberType, std::string>) {
std::println(" {} before: {}", name, obj.[:m:]);
obj.[:m:] = "Modified";
std::println(" {} before: {}", name, obj.[:m:]);
}
}
}
template <typename T> constexpr void CallFunctions(T &obj) {
constexpr auto ctx{std::meta::access_context::current()};
constexpr auto all_members{define_static_array(members_of(^^T, ctx))};
template for (constexpr std::meta::info mem : all_members) {
if constexpr ((is_function(mem) || is_function_template(mem)) &&
has_identifier(mem)) {
constexpr auto name{identifier_of(mem)};
std::println(" Found: {}", name);
if constexpr (name == std::string_view("AddNumbers")) {
StrictInt a{10};
StrictInt b{32};
if constexpr (is_function_template(mem)) {
if constexpr (requires { obj.template[:mem:](a, b); }) {
std::println(" {}({}, {}) = {}", name, a, b,
obj.template[:mem:](a, b));
} else {
std::println(" Trying with int parameters:");
int x{10};
int y{20};
std::println(" {}({}, {}) = {}", name, x, y,
obj.template[:mem:](x, y));
}
} else if constexpr (requires { obj.[:mem:](a, b); }) {
std::println(" {}({}, {}) = {}", name, a, b, obj.[:mem:](a, b));
}
} else if constexpr (name == std::string_view("GetDisplayName")) {
auto label{obj.[:mem:]()};
std::println(" GetDisplayName() = {}", label);
}
}
}
}
// template <>
// struct std::formatter<StrictInt> : std::formatter<int> {
// auto format(const StrictInt &si, std::format_context &ctx) const {
// return std::formatter<int>::format(si.value, ctx);
// }
// };
struct TwoFloats {
float x{1.0f};
float y{2.0f};
};
struct Simple {
char a{'a'};
bool b{true};
double c{1.1};
[[= noReflect]] int d{1};
float e{1.5f};
std::string f{"Hello"};
TwoFloats myTwoFloats{};
int AddNumbers(IsInt auto a, IsInt auto b) { return a + b; }
int AddNumbers(StrictInt a, StrictInt b) { return a.value + b.value; }
std::string GetDisplayName() const { return "Name: " + f; }
};
int main() {
Simple obj;
std::println("=== Type Inspection ===");
InspectType(obj);
std::println("\n=== Field Modification ===");
ModifyFields(obj);
std::println("\n=== Function Invocation ===");
CallFunctions(obj);
}