Example
struct foo {
std::size_t bar;
};
int main() {
std::cout << std::meta::offset_of(^foo::bar); // 0
std::cout << std::meta::size_of(^foo::bar); // 8
std::cout << std::meta::alignment_of(^foo::bar); // 8
}
Puzzle
- Can you implement
layout
function which returns a range ofdesc
describing the layout for given typeT
?
struct foo {
char a;
int b;
float c;
};
struct desc {
std::size_t size{};
std::size_t offset{};
std::size_t alignment{};
constexpr auto operator<=>(const desc&) const = default;
};
template<class T, class TDesc>
concept range_of = std::ranges::range<T> and std::same_as<std::ranges::range_value_t<T>, TDesc>;
template<class T>
[[nodiscard]] constexpr auto layout() -> range_of<desc> auto; // TODO
static_assert(std::array{desc{1u, 0u, 1u}, desc{4u, 4u, 4u}, desc{4u, 8u, 4u}} == layout<foo>());
Solutions
struct foo {
char a;
int b;
float c;
};
struct desc {
std::size_t size{};
std::size_t offset{};
std::size_t alignment{};
constexpr auto operator<=>(const desc&) const = default;
};
template<class T, class TDesc>
concept range_of = std::ranges::range<T> and std::same_as<std::ranges::range_value_t<T>, TDesc>;
consteval std::size_t vectorSize(auto vec) noexcept {
return vec.size();
}
template <typename T>
[[nodiscard]] constexpr auto layout() noexcept -> range_of<desc> auto {
std::array<desc, vectorSize(std::meta::nonstatic_data_members_of(^T))> layouts;
int index = 0;
[: expand(std::meta::nonstatic_data_members_of(^T)) :] >> [&layouts, &index]<auto t>() mutable {
layouts[index] = desc {.size = size_of(t), .offset = offset_of(t), .alignment = alignment_of(t)};
index ++;
};
return layouts;
}
struct foo {
char a;
int b;
float c;
};
struct desc {
std::size_t size{};
std::size_t offset{};
std::size_t alignment{};
constexpr auto operator<=>(const desc&) const = default;
};
template <class T, class TDesc>
concept range_of = std::ranges::range<T> and std::same_as<std::ranges::range_value_t<T>, TDesc>;
template <class T>
[[nodiscard]] constexpr auto layout() -> range_of<desc> auto {
std::array<desc, std::size(nonstatic_data_members_of(^T))> layout{};
[:expand(nonstatic_data_members_of(^T)):] >> [&, i = 0]<auto V>() mutable {
layout[i++] = {.size = std::meta::size_of(V),
.offset = std::meta::offset_of(V),
.alignment = std::meta::alignment_of(V)};
};
return layout;
}
static_assert(std::array{desc{1u, 0u, 1u}, desc{4u, 4u, 4u}, desc{4u, 8u, 4u}} == layout<foo>());