-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcpp_rs_reflect.h
More file actions
101 lines (89 loc) · 4.49 KB
/
Copy pathcpp_rs_reflect.h
File metadata and controls
101 lines (89 loc) · 4.49 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
#pragma once
// Compile-time reflection over aggregate types. This is what makes the JSON
// bridge generic: no per-type registration code is required.
#include <cstddef>
#include <type_traits>
#include <utility>
namespace cpp_rs::reflect {
namespace detail {
/// Converts to anything except `Owner`, so it never hijacks a copy/move constructor.
template <typename Owner>
struct any_field {
template <typename U, typename = std::enable_if_t<!std::is_same_v<Owner, std::remove_cvref_t<U>>>>
constexpr operator U() const noexcept;
};
template <typename T, typename... Probes>
consteval std::size_t count_fields() {
if constexpr (requires { T{Probes{}..., any_field<T>{}}; }) {
return count_fields<T, Probes..., any_field<T>>();
} else {
return sizeof...(Probes);
}
}
} // namespace detail
template <typename T>
inline constexpr std::size_t field_count = detail::count_fields<std::remove_cvref_t<T>>();
template <typename T>
inline constexpr bool is_reflectable_aggregate_v =
std::is_aggregate_v<std::remove_cvref_t<T>> && !std::is_array_v<std::remove_cvref_t<T>>;
/// Calls `visitor` with references to every member of `value`, in declaration order.
template <typename T, typename Visitor>
constexpr decltype(auto) visit_fields(T &&value, Visitor &&visitor) {
constexpr std::size_t count = field_count<T>;
static_assert(count <= 16, "cpp_rs reflection supports up to 16 fields per aggregate");
if constexpr (count == 0) {
return std::forward<Visitor>(visitor)();
} else if constexpr (count == 1) {
auto &&[f0] = value;
return std::forward<Visitor>(visitor)(f0);
} else if constexpr (count == 2) {
auto &&[f0, f1] = value;
return std::forward<Visitor>(visitor)(f0, f1);
} else if constexpr (count == 3) {
auto &&[f0, f1, f2] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2);
} else if constexpr (count == 4) {
auto &&[f0, f1, f2, f3] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3);
} else if constexpr (count == 5) {
auto &&[f0, f1, f2, f3, f4] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4);
} else if constexpr (count == 6) {
auto &&[f0, f1, f2, f3, f4, f5] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5);
} else if constexpr (count == 7) {
auto &&[f0, f1, f2, f3, f4, f5, f6] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5, f6);
} else if constexpr (count == 8) {
auto &&[f0, f1, f2, f3, f4, f5, f6, f7] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5, f6, f7);
} else if constexpr (count == 9) {
auto &&[f0, f1, f2, f3, f4, f5, f6, f7, f8] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5, f6, f7, f8);
} else if constexpr (count == 10) {
auto &&[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9);
} else if constexpr (count == 11) {
auto &&[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10);
} else if constexpr (count == 12) {
auto &&[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11);
} else if constexpr (count == 13) {
auto &&[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12);
} else if constexpr (count == 14) {
auto &&[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
f13);
} else if constexpr (count == 15) {
auto &&[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
f13, f14);
} else {
auto &&[f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12, f13, f14, f15] = value;
return std::forward<Visitor>(visitor)(f0, f1, f2, f3, f4, f5, f6, f7, f8, f9, f10, f11, f12,
f13, f14, f15);
}
}
} // namespace cpp_rs::reflect