This is the third question in the series of zero-size objects and subobjects today.
The standars clearly implies that member subobjects cannot have zero size whereas base class subobjects can.
struct X {}; //empty class, complete objects of class X have nonzero size
struct Y:X { char c; }; //Y's size may be 1
struct Z {X x; char c;}; //Z's size MUST be greater than 1
Why not allow zero-size member-subobjects JUST LIKE zero-size base-class-subobjects?
TIA
EDITING after Konrad’s answer:
consider the following example:
struct X{};
struct D1:X{};
struct D2:D1, X {}; //D2 has 2 distinct subobjects of type X, can they both be 0 size and located at the same address?
If two base class subobjects of the same type X, as in my example, can be located at the same address, so should be able to member subobjects. If they cannot, then compiler treats this case specially and so can it treat Konrad’s example(see answer below) specially and disallow zero-size member subobjects if there are multiple of the same type in the same class. Where am I wrong?
The compiler could conditionally allow zero-size member objects as well as base classes, sure, but it would be more complex. The empty base class optimization always applies, regardless of type. Any time the compiler sees a class derive from a class with no data members, it can use the empty base class optimization.
Following @Konrad Rudolphs example through, with member objects, it’d have to check the type, verify that no other object of the same type exists at that location, and then maybe apply your optimization. Well, unless the member object is located at the end of the containing class. If so, then the object’s “real” (non-zero) size would protrude past the end of the containing class, which would also be an error. That can never happen in the base class case because we know that the base class is located at the beginning of the derived class, and the derived class has non-zero size.
So such an optimization would be more complex, more subtle, and more likely to break in unexpected ways.
I can’t cite any cases off-hand where zero-size member objects would definitely break, but I’m not convinced that they don’t exist either. I’ve already pointed out a couple of limitations that don’t exist in the base-class case, and most likely, more exist. So the question is, how much complexity and uncertainty should the language allow just to make one rarely useful optimization possible?