
On 7/20/2013 1:03 PM, Andrew Ho wrote:
It's templated so that multiple inheritance doesn't kill the empty base optimization.
With which compiler? I tests using gcc 4.8.1 and as far as I can tell there's no difference between using templated empty_base vs. untemplated empty_base. Even some times with templated empty_base gcc 4.8.1 would not do empty base class optimization using enough multiple inheritance.
VS2012 doesn't appear to do empty base class optimization for multiple inheritance at all, so templated/untemplated also makes no difference here.
In addition to this, I thought empty_base is there to transform the operation into single inheritance anyways. VS2012 and gcc 4.8.1 both seem to be able to handle single inheritance optimizations fine even if empty_base isn't templated.
// can replace with plain old operators and run the same test. // I'm just using operators2 because it's much easier for me to test templated/untemplated empty_base class MyClass : public boost::operators2::addable< MyClass > ,public boost::operators2::subtractable< MyClass > ,public boost::operators2::multipliable< MyClass > ,public boost::operators2::dividable< MyClass > ,public boost::operators2::xorable< MyClass > // comment out to drop size back to sizeof(int) instead of 8 { // commented: gcc fails to perform empty base class optimizations, sizeof(MyA) = 5 // uncommented: gcc appears to work and sizeof(MyA) = sizeof(int) int val;
// ... OP= operators omitted for clarity };
IIRC the first member sharing a base class would break EBO. i.e. struct Foo : addable< Foo > { // <snip> }; struct Bar : addable< Bar > { Foo foo; // <snip> }; Bar bar; Without the template parameter both Bar and Foo would derive from addable and the standard would forbid static_cast<addable*>(&bar) == static_cast<addable*>(&bar.foo).