365.md

January 22, 2024 ยท View on GitHub

Info

Example

struct foo;
[[maybe_unused]] constexpr auto _ =
  define_class(^foo, {std::meta::nsdm_description(^int, {.name = "bar"})});
foo f{.bar = 42}; // has bar int member

https://godbolt.org/z/aqxanTe3r

Puzzle

  • Can you implement template alias pack which will pack given struct by sorting members by their size?
template<class T> using pack; // TODO

struct unpacked {
  short s;
  int i;
  bool b;
};
static_assert(12 == sizeof(unpacked));

using packed = pack<unpacked>;
static_assert(8 == sizeof(packed));
static_assert(requires(packed p) { p.i; p.s; p.b; });

https://godbolt.org/z/hnPvsE9h3

Solutions

namespace detail {
template<class T> struct packed;
template<class T> [[nodiscard]] consteval auto pack() {
  std::vector members = std::meta::nonstatic_data_members_of(^T);
  sort(members, [](auto lhs, auto rhs) consteval { return std::meta::size_of(lhs) < std::meta::size_of(rhs); });
  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)}});
  }
  return define_class(^packed<T>, new_members);
}
} // namespace detail
template<class T> using pack = [:detail::pack<T>():];

struct unpacked {
  short s;
  int i;
  bool b;
};
static_assert(12 == sizeof(unpacked));

using packed = pack<unpacked>;
static_assert(8 == sizeof(packed));
static_assert(requires(packed p) { p.i; p.s; p.b; });

https://godbolt.org/z/ExYfTv4nK