1

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.

Reza
  • 360
  • 3
  • 17
  • 1
    your minimal example is not about getting the size of the struct. It is about asserting a specific size. – 463035818_is_not_an_ai Aug 21 '20 at 08:55
  • @idclev463035818 check the commented out part in the function `bytesize`, this is the part which does not work – Reza Aug 21 '20 at 08:57
  • there is no function bytesize, please include the code in the question – 463035818_is_not_an_ai Aug 21 '20 at 08:57
  • 1
    What is the outcome you expect? What is the output you get? Please take some time to [the help pages](http://stackoverflow.com/help), take the SO [tour], read [ask], as well as [this question checklist](https://codeblog.jonskeet.uk/2012/11/24/stack-overflow-question-checklist/). – Some programmer dude Aug 21 '20 at 08:58
  • 2
    By the way, you *are* aware of [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member) – Some programmer dude Aug 21 '20 at 09:00
  • @Someprogrammerdude Yes I'm aware of this issue, that's why I'm using boost::hana. – Reza Aug 21 '20 at 09:06
  • @idclev463035818 The linked question which I "instructed" to read does mention the problem with padding, I assumed that mentionig it another time does not aid the cause but I can add it again in the question – Reza Aug 21 '20 at 09:20
  • @Scheff ups you're right, copy paste error – Reza Aug 21 '20 at 09:25
  • FYI: I got rid of the compile error by adding `else return 0;` but it still doesn't match the `static_assert()`: [Fixed _here_ on CompilerExplorer](https://godbolt.org/z/1o63fM) – Scheff's Cat Aug 21 '20 at 09:34
  • Why do you assume that Boost Hana does something that makes the compiler omit the padding? Have you ran the code through the preprocessor to see what all the macro invocations really expand to, and what the structure really is? – Some programmer dude Aug 21 '20 at 09:34
  • @Someprogrammerdude boost::hana doesn't do anything with the padding, it just gives me the possibility to cycle my struct members at compile time – Reza Aug 21 '20 at 09:39
  • Okay I think I get you now: You use Boost Hana to add some meta-data and reflection abilities available. Like for example enumerate the individual members of the structure, and getting their respective size. – Some programmer dude Aug 21 '20 at 09:47
  • exactly the BOOST_HANA_DEFINE_STRUCT macro gives me this ability – Reza Aug 21 '20 at 09:48
  • Now please answer us this: Why do you need this? What is the *actual* problem you need to solve? Always please ask about the actual problem directly, possibly presenting what you have tried (like in this question) as your attempt, including a description of the problems you have with your attempt. It's okay if it's just plain curiosity, but then please state so in the question itself. We might be able to help you with the original problem instead, and maybe have *other* solutions. – Some programmer dude Aug 21 '20 at 09:48
  • @Someprogrammerdude The problem is described in the first sentence of the question, I am asking this question to experts in boost::hana, that's why I'm inclundig this tag, I assumed therefore I don't have to explain the workings of boost::hana to ask my question – Reza Aug 21 '20 at 11:16

2 Answers2

2

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

Jarod42
  • 203,559
  • 14
  • 181
  • 302
0

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.

Nick
  • 9,962
  • 4
  • 42
  • 80