编译结构的大小减去填充

问题描述

我有一个与此question类似的问题。 我想在编译时获得结构的大小,包括所有未添加编译器特定填充的子结构。

-property:Platform

由于我不想包含填充,我希望结构/p:Platform的大小为18(包括子结构struct Bar { BOOST_HANA_DEFINE_STRUCT(Bar,(std::uint8_t,a),(std::uint16_t,b) ); }; struct Foo { BOOST_HANA_DEFINE_STRUCT(Foo,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>(),[](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); 的大小),但是链接问题中的代码确实在计算中包括填充,我的大小为19。问题在于函数应该在遇到的所有结构上递归调用字节大小。

可以找到一个无法按预期运行的最小示例here

解决方法

返回的类型不是您期望的类型(附加&&),您会遇到问题。 std::decay_t解决了该问题:

return hana::fold_left(
    hana::accessors<T>(),[](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;
    });

Demo

,

结构的尺寸更大,因为存在填充对齐方式

https://en.wikipedia.org/wiki/Data_structure_alignment

gccclang上,您可以使用__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。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...