Reza
Reza

Reputation: 360

Compile size of a struct minus padding recusively

I have a similar Problem as in this question. I want to get the size of struct at compile time, including all the substructs without the compiler specific padding added.

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

As I don't want to include the padding, I expect the size of the struct Foo to be 18 (including the size of the substruct Bar) but the code in the linked question does include the padding in the calculation and gives me a size of 19. The problem lies therein that the function should call bytesize recursively on all structs it encounters.

A minimal example which does not work as intended can be found here.

Upvotes: 1

Views: 176

Answers (2)

Jarod42
Jarod42

Reputation: 218098

You have issue with returned types which are not what you expect (extra &&). std::decay_t fixes the issue:

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

Demo

Upvotes: 2

Nick
Nick

Reputation: 10539

Size of the structure is more, because there is padding or alignment.

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

On gcc and clang you can use __attribute__((__packed__))

struct Bar {
  BOOST_HANA_DEFINE_STRUCT(Bar,
      (std::uint8_t, a),
      (std::uint16_t, b)
  );
} __attribute__((__packed__));

Example
https://godbolt.org/z/odMTEs

Note, on x86, packed structs does NOT have negative effect. Not measurable at least.

On Arm they also work "fast enought".

However on some other architectures they might be really slow or even they can "crash" the CPU.

Upvotes: 0

Related Questions