-
Notifications
You must be signed in to change notification settings - Fork 73
/
Copy path366.md
149 lines (115 loc) · 4.05 KB
/
366.md
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
<details open><summary>Info</summary><p>
* **Did you know about C++26 static reflection proposal (6/N)?**
* https://wg21.link/P2996
</p></details><details open><summary>Example</summary><p>
```cpp
template<auto N> struct counter {
static constexpr auto value = N;
};
[[nodiscard]] consteval auto next() {
for (auto i = 0;; ++i) {
if (auto mi = substitute(^counter, { std::meta::reflect_value(i) }); std::meta::is_incomplete_type(mi)) {
return std::meta::value_of<decltype(i)>(std::meta::static_data_members_of(mi)[0]);
}
}
}
static_assert(next() == 0);
static_assert(next() == 1);
```
> https://godbolt.org/z/91M56a5dd
</p></details><details open><summary>Puzzle</summary><p>
* **Can you implement compile-time type list?**
```cpp
template<class T> using append_t;// TODO
template<auto = []{}> using get_list_t; // TODO
int main() {
static_assert(typeid(get_list_t<>{}) == typeid(type_list<>));
append_t<int>{};
static_assert(typeid(get_list_t<>{}) == typeid(type_list<int>));
append_t<float>{};
static_assert(typeid(get_list_t<>{}) == typeid(type_list<int, float>));
}
```
> https://godbolt.org/z/W7s5TW8ss
</p></details>
</p></details><details><summary>Solutions</summary><p>
```cpp
template<auto> struct type_list_impl;
consteval auto append(auto new_member) {
std::vector<std::meta::info> members{};
for (auto i = 0;; ++i) {
if (auto mi = substitute(^type_list_impl, { std::meta::reflect_value(i) }); std::meta::is_incomplete_type(mi)) {
std::vector<std::meta::nsdm_description> new_members{};
for (const auto& member: members) {
new_members.push_back({std::meta::type_of(member), {.name = std::meta::name_of(member)}});
}
const char name[]{'_', char(i+'0'), 0};
new_members.push_back({{new_member}, {.name = std::string_view(name, 2)}});
return define_class(mi, new_members);
} else {
members = std::meta::nonstatic_data_members_of(mi);
}
}
}
consteval auto get_list(auto type_list) {
std::vector<std::meta::info> members{};
for (auto i = 0;; ++i) {
if (auto mi = substitute(^type_list_impl, { std::meta::reflect_value(i) }); std::meta::is_incomplete_type(mi)) {
break;
} else {
members = std::meta::nonstatic_data_members_of(mi);
}
}
std::vector<std::meta::info> new_members{};
for (auto member : members) {
new_members.push_back(std::meta::type_of(member));
}
return substitute(type_list, new_members);
}
template<class...> struct type_list{};
template<class T> using append_t = [:append(^T):];
template<auto = []{}> using get_list_t = [:get_list(^type_list):];
int main() {
static_assert(typeid(get_list_t<>{}) == typeid(type_list<>));
append_t<int>{};
static_assert(typeid(get_list_t<>{}) == typeid(type_list<int>));
append_t<float>{};
static_assert(typeid(get_list_t<>{}) == typeid(type_list<int, float>));
}
```
> https://godbolt.org/z/P6sTdPEG8
```cpp
template<class...> struct type_list {};
template<auto> struct nth { auto friend get(nth); auto friend get(nth); };
template<auto N, class T> struct set { auto friend get(nth<N>) { return T{}; } };
template<class T, template<class...> class TList, class... Ts> auto append_impl(TList<Ts...>) -> TList<Ts..., T>;
template<class T, auto N = 0, auto unique = []{}>
consteval auto append() {
if constexpr (requires { get(nth<N>{}); }) {
append<T, N+1, unique>();
} else if constexpr (N == 0) {
void(set<N, type_list<T>>{});
} else {
void(set<N, decltype(append_impl<T>(get(nth<N-1>{})))>{});
}
}
template<auto unique = []{}, auto N = 0>
consteval auto get_list() {
if constexpr (requires { get(nth<N>{}); }) {
return get_list<unique, N+1>();
} else if constexpr (N == 0) {
return type_list{};
} else {
return get(nth<N-1>{});
}
}
int main() {
static_assert(typeid(get_list()) == typeid(type_list<>));
append<int>();
static_assert(typeid(get_list()) == typeid(type_list<int>));
append<float>();
static_assert(typeid(get_list()) == typeid(type_list<int, float>));
}
```
> https://godbolt.org/z/d7GrW1j76
</p></details>