Info
-
Did you know that with gnu:C++26 a more parts of static reflection can be emulated?
Example
struct foo { int a{}; int b{}; };
struct bar { int a{}; };
constexpr auto structs = meta_find<"struct">;
static_assert(2uz == structs.size());
static_assert("foo" == structs[0]);
static_assert("bar" == structs[1]);
static_assert(reflexpr<foo>);
constexpr auto f = typeof<[] { return structs[0]; }>{.a = 1, .b = 2};
static_assert(1 == f.a and 2 == f.b);
constexpr auto t = to_tuple(f);
static_assert("a" == std::get<0>(t).name and 1 == std::get<0>(t).value);
static_assert("b" == std::get<1>(t).name and 2 == std::get<1>(t).value);
int main() {
reflexpr auto b = bar{};
// ...
constexpr auto name = std::find(structs.cbegin(), structs.cend(), type_name<decltype(b)>());
static_assert(name != structs.cend());
static_assert(42 == typeof<[] { return *name; }>{42}.a);
}
Puzzle
Given reflection primitives can you implemnt all_structs_field_names which returns combined list of all field names from all structs in the file?
struct foo {
int a{};
int b{};
};
static_assert(reflexpr<foo>);
struct bar {
int c{};
};
static_assert(reflexpr<bar>);
struct baz {
int d{};
int e{};
int f{};
};
static_assert(reflexpr<baz>);
[[nodiscard]] constexpr auto all_structs_field_names(); // TODO
constexpr auto ns = all_structs_field_names();
static_assert(6uz == ns.size());
static_assert("a" == ns[0]);
static_assert("b" == ns[1]);
static_assert("c" == ns[2]);
static_assert("d" == ns[3]);
static_assert("e" == ns[4]);
static_assert("f" == ns[5]);
Solutions
[[nodiscard]] constexpr auto all_structs_field_names() {
return []<auto... Is>(std::index_sequence<Is...>) {
return std::apply(
[](auto... elements) {
static_vector<std::string_view, sizeof...(elements)> v{};
(..., v.push_back(elements.name));
return v;
},
std::tuple_cat(
to_tuple(typeof<[] { return meta_find<"struct">[Is]; }>{})...));
}(std::make_index_sequence<meta_find<"struct">.size()>{});
}
[[nodiscard]] constexpr auto members_to_names(auto& out, auto struct_members) {
constexpr auto num_members = std::tuple_size_v<decltype(struct_members)>;
[&out, &struct_members]<auto... Ns>(std::index_sequence<Ns...>) {
(
out.push_back(std::get<Ns>(struct_members).name)
, ...
);
}(std::make_index_sequence<num_members>{});
}
template
<std::size_t index>
[[nodiscard]] constexpr auto struct_instance() {
return typeof<[] { return structs[index]; }>{};
};
template
<std::size_t MaxSize = 8>
[[nodiscard]] constexpr auto all_structs_field_names() {
static_vector<std::string_view, MaxSize> names{};
[&names]<auto... Ns>(std::index_sequence<Ns...> ns) {
(
members_to_names(names, to_tuple(struct_instance<Ns>()))
, ...
);
}(std::make_index_sequence<structs.size()>{});
return names;
}