2

Clang seems not to do empty base class optimization in this scenario:

struct A { };                          //sizeof(A) == 1 -> OK
struct B : public A { int _intValue; };//sizeof(B) == 4 -> OK, EBCO works here
struct C : public A { B _bValue; };    //sizeof(C) == 8 -> ??? Not OK

It seems g++ behaves the same (or similar) way. Is this normal? I think EBCO should kick in here.

Am I missing something that would make it illegal here?

Mat
  • 202,337
  • 40
  • 393
  • 406
orlin
  • 61
  • 2
  • I think this is not a candidate for EBCO. – John Dibling Jul 24 '13 at 19:34
  • 2
    2 objects of type A can't have the same address. C contains 2 A, they can't be at the same address, so that pushes B further. A cleverer ABI might have managed to stick the second A somewhere in the middle of _intvalue, but if you added enough A you would eventually increase the size anyway. – Marc Glisse Jul 24 '13 at 19:38
  • 2
    http://stackoverflow.com/questions/547290/is-the-empty-base-optimization-in-gcc-configurable?rq=1#547439 and others. – Marc Glisse Jul 24 '13 at 20:06
  • I am not sure how to respond here with an answer to my own original question (which was edited): is there any setting or option to use in order to work around this problem. I came up with a work around which is acceptable to me, based on the comments from Marc Glisse: `template struct A { }; struct B : A { int _int; }; struct C : A { B _b; };` I hope this helps someone. Thank you all for your comments, and thank you C++ for leaving a back door for working around all of your rules:) Orlin++ P.S. I really don't like this rule though... It still makes no sense to me. – orlin Jul 25 '13 at 11:11

2 Answers2

0

To me the difference seems to come from the fact that

&B == &(B._intValue)

vs

&C != &(C._bValue._intValue)

because &(instance of C) == &(instance of B) should be invalid, while &(instance of B) == &first member of (instance of B) is valid in case of first member of (instance of B) being a basic type (char, int, ...).

I don't think it has anything to do with EBCO really.

griffin
  • 1,261
  • 8
  • 24
  • I would totally agree if there were any virtualization involved, but these are POD. This will introduce quite a big bloat especially if your derived class is 8byte aligned. Besides, MS compiler optimizes this, so it must be acceptable. – orlin Jul 24 '13 at 19:57
  • @user2339673: "MS compiler optimizes this, so it must be acceptable" - that's nonsense. If it turns out VC is wrong in doing that optimization according to the C++ standard, you're stuck with non-portable code - that's acceptable if you only target VC. It's not if you need portable code. – Mat Jul 24 '13 at 20:13
  • Mat, I didn't want to turn this into MS vs CLang discussion, because MS optimization is terrible most of the time, and my intent is to stop using MS completely and switch to CLang. I can't find such a requirement in the C++ standard. Can you please point me to it? – orlin Jul 24 '13 at 20:34
  • I myself only know this from the C standard - I don't know if it's in the C++ standard. But as C++ is ought to be _mostly_ compatible with C, and _most_ c++ compilers can also compile C, this might apply here as well. You'll probably have to search for "identity keeping" or the like to find what you're looking for. – griffin Jul 25 '13 at 09:02
0

It looks to me like clang is aligning to 4 bytes, as that might be optimal memory access on your platform. How did you compile that code?

MattD
  • 380
  • 1
  • 15
  • Yes, clang is aligning to 4 bytes, because struct B contains an integer (4 bytes), if it contained a long long, the bloat was going to be 8 bytes. I compiled this on 32 WinXP and 64 Ubuntu. – orlin Jul 25 '13 at 10:50