递归编译结构减去填充的大小
Compile size of a struct minus padding recusively
我遇到了与此 类似的问题。
我想在编译时获取结构的大小,包括所有未添加编译器特定填充的子结构。
struct Bar {
BOOST_HANA_DEFINE_STRUCT(Bar,
(std::uint8_t, a),
(std::uint16_t, b)
);
};
struct Foo {
BOOST_HANA_DEFINE_STRUCT(Foo,
(std::uint8_t, a),
(std::uint16_t, b),
(std::uint32_t, c),
(std::uint64_t, d),
(Bar, bar)
);
};
template <typename T>
constexpr auto bytesize() -> size_t
{
if constexpr (std::is_arithmetic<T>::value || std::is_enum<T>::value)
return sizeof(T);
else if constexpr (std::is_class<T>::value)
{
return hana::fold_left(
hana::accessors<T>(), 0, [](auto total, auto member) {
// I want to call bytesize recusively here:
return bytesize<decltype(hana::second(member)(std::declval<T>()))>() + total;
});
}
}
static_assert(bytesize<Foo>() == 18);
因为我不想包含填充,所以我希望结构 Foo
的大小为 18(包括子结构 Bar
的大小),但是链接中的代码问题确实在计算中包含了填充,并给出了 19 的大小。问题在于该函数应该在它遇到的所有结构上递归调用 bytesize。
可以找到一个没有按预期工作的最小示例 here。
结构的大小比较多,因为有padding或者alignment.
https://en.wikipedia.org/wiki/Data_structure_alignment
在 gcc
和 clang
上,您可以使用 __attribute__((__packed__))
struct Bar {
BOOST_HANA_DEFINE_STRUCT(Bar,
(std::uint8_t, a),
(std::uint16_t, b)
);
} __attribute__((__packed__));
例子
https://godbolt.org/z/odMTEs
注意,在 x86 上,打包结构没有负面影响。至少不可测量。
在 Arm 上,它们也“足够快”地工作。
然而在其他一些架构上它们可能真的很慢甚至会“崩溃”CPU。
您对返回的类型有疑问,这不是您所期望的(额外 &&
)。 std::decay_t
修复了问题:
return hana::fold_left(
hana::accessors<T>(), 0, [](auto total, auto member) {
using member_type = std::decay_t<decltype(hana::second(member)(std::declval<T>()))>;
constexpr auto member_size = bytesize<member_type>();
return total + member_size;
});
我遇到了与此
struct Bar {
BOOST_HANA_DEFINE_STRUCT(Bar,
(std::uint8_t, a),
(std::uint16_t, b)
);
};
struct Foo {
BOOST_HANA_DEFINE_STRUCT(Foo,
(std::uint8_t, a),
(std::uint16_t, b),
(std::uint32_t, c),
(std::uint64_t, d),
(Bar, bar)
);
};
template <typename T>
constexpr auto bytesize() -> size_t
{
if constexpr (std::is_arithmetic<T>::value || std::is_enum<T>::value)
return sizeof(T);
else if constexpr (std::is_class<T>::value)
{
return hana::fold_left(
hana::accessors<T>(), 0, [](auto total, auto member) {
// I want to call bytesize recusively here:
return bytesize<decltype(hana::second(member)(std::declval<T>()))>() + total;
});
}
}
static_assert(bytesize<Foo>() == 18);
因为我不想包含填充,所以我希望结构 Foo
的大小为 18(包括子结构 Bar
的大小),但是链接中的代码问题确实在计算中包含了填充,并给出了 19 的大小。问题在于该函数应该在它遇到的所有结构上递归调用 bytesize。
可以找到一个没有按预期工作的最小示例 here。
结构的大小比较多,因为有padding或者alignment.
https://en.wikipedia.org/wiki/Data_structure_alignment
在 gcc
和 clang
上,您可以使用 __attribute__((__packed__))
struct Bar {
BOOST_HANA_DEFINE_STRUCT(Bar,
(std::uint8_t, a),
(std::uint16_t, b)
);
} __attribute__((__packed__));
例子
https://godbolt.org/z/odMTEs
注意,在 x86 上,打包结构没有负面影响。至少不可测量。
在 Arm 上,它们也“足够快”地工作。
然而在其他一些架构上它们可能真的很慢甚至会“崩溃”CPU。
您对返回的类型有疑问,这不是您所期望的(额外 &&
)。 std::decay_t
修复了问题:
return hana::fold_left(
hana::accessors<T>(), 0, [](auto total, auto member) {
using member_type = std::decay_t<decltype(hana::second(member)(std::declval<T>()))>;
constexpr auto member_size = bytesize<member_type>();
return total + member_size;
});