1

I have a struct Foo which contains a nested struct Bar. These structs only contain POD types. My problem is that the size of Foo is larger than it would have been if I copied all the members of Bar:

#include <iostream>
#include <string>

struct Bar {
    double a;
    long long b;
    int c;
};

struct Foo {
    Bar b;
    int d;
};

struct Foo2 {
    double a;
    long long b;
    int c;
    int d;
};

int main()
{
  std::cout << sizeof(Foo) << std::endl;
  std::cout << sizeof(Bar) << std::endl;
  std::cout << sizeof(Foo2) << std::endl;
}

32 24 24

Demo

I understand that this is happening because Bar gets padded to 24 bytes so Foo adds a single int which then gets padded to 32 bytes. I don't want to mark Bar or Foo as packed. I was wondering if there is any way to tell the compiler to not store Bar as a struct but to just include its members? Something like:

struct Foo {
    inline Bar b; // Keyword inline doesn't work here.
    int d;
};
Benjy Kessler
  • 7,356
  • 6
  • 41
  • 69
  • `I don't want to mark Bar or Foo as packed.` Why not? – eerorika Dec 01 '20 at 07:41
  • @eerorika possible degrade in performance? – Tony Tannous Dec 01 '20 at 07:45
  • 1
    Several reasons: 1. It makes the code less readable 2. It might degrade performance 3. Bar is from an external library so I can't modify it. 4. Not sure how portable it is. – Benjy Kessler Dec 01 '20 at 07:46
  • 2
    @TonyTannous OP is trying to only overlap members with padding, not to misalign the members. – eerorika Dec 01 '20 at 07:46
  • Could you explain why this is a problem in your case. Padding could vary depening on which compiler, version and compiler flags are used and how the member itself are used. So you actually cannot guarantee that `Foo2` and `Foo` have the same aligment. – t.niese Dec 01 '20 at 07:55
  • [Standard-layout and tail padding](https://stackoverflow.com/q/53837373/995714), [Packing nested structs in C++](https://stackoverflow.com/q/44023837/995714), [When extending a padded struct, why can't extra fields be placed in the tail padding?](https://stackoverflow.com/q/24110347/995714) – phuclv Dec 01 '20 at 08:29

1 Answers1

2

We must allow the member to be a potentially-overlapping subobject. There are two ways: 1. Instead of using a member, inherit from Bar or 2. Use the attribute [[no_unique_address]] (C++20).

Technically, being potentially-overlapping is sufficient to allow the compiler to re-use the padding. However, unfortunately being able to reuse the padding doesn't guarantee the re-use and in practice, certain language implementations do not re-use padding of trivially copyable standard layout types. We can work around this by making the sub object non-trivially-copyable or non-standard-layout.

I can't modify [Bar]

Then making it non-trivially-copyable-standard-layout type won't be possible, and therefore certain language implementations won't reuse the padding.

eerorika
  • 232,697
  • 12
  • 197
  • 326