Empty base optimization is great. However, it comes with the following restriction:
Empty base optimization is prohibited if one of the empty base classes is also the type or the base of the type of the first non-static data member, since the two base subobjects of the same type are required to have different addresses within the object representation of the most derived type.
To explain this restriction, consider the following code. The static_assert
will fail. Whereas, changing either Foo
or Bar
to instead inherit from Base2
will avert the error:
#include <cstddef>
struct Base {};
struct Base2 {};
struct Foo : Base {};
struct Bar : Base {
Foo foo;
};
static_assert(offsetof(Bar,foo)==0,"Error!");
I understand this behavior completely. What I do not understand is why this particular behavior exists. It was obviously added in for a reason, since it is an explicit addition, not an oversight. What is a rationale for this?
In-particular, why should the two base subobjects be required to have different addresses? In the above, Bar
is a type and foo
is a member variable of that type. I don't see why the base class of Bar
matters to the base class of the type of foo
, or vice-versa.
Indeed, I if anything, I would expect that &foo
is the same as the address of the Bar
instance containing it—as it is required to be in other situations (1). After-all, I'm not doing anything fancy with virtual
inheritance, the base classes are empty regardless, and the compilation with Base2
shows that nothing breaks in this particular case.
But clearly this reasoning is incorrect somehow, and there are other situations where this limitation would be required.
Let's say answers should be for C++11 or newer (I'm currently using C++17).
(1) Note: EBO got upgraded in C++11, and in-particular became mandatory for StandardLayoutType
s (though Bar
, above, is not a StandardLayoutType
).
Base *a = new Bar(); Base *b = a->foo;
witha==b
, buta
andb
are clearly different objects (perhaps with different virtual method overrides). – Mirna