Skip to content

Latest commit

 

History

History
126 lines (100 loc) · 3.28 KB

314.md

File metadata and controls

126 lines (100 loc) · 3.28 KB
Info

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);
}

https://godbolt.org/z/PPsn4KM7Y

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]);

https://godbolt.org/z/M1KdE8xET

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()>{});
}

https://godbolt.org/z/hnKTfs8bx

[[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;
}

https://godbolt.org/z/z56h5xahv