[Operators] empty_base should be untemplated?
I've noticed about the empty_base class is that it's templated with type T, and I don't think it should be. Fyi, the empty_base class is there to turn multiple inheritance into a single inheritance chain (due to compiler deficiencies/object size bloat on at least Visual Studio). I don't see why this empty_base should be templated, and it would be better suited if it wasn't since all I can think it does is make the compiler work harder. Does anyone know why it was templated to begin with? Additionally, are we safe to change empty_base to be not use templates?
on Thu Jul 18 2013, Andrew Ho
I've noticed about the empty_base class is that it's templated with type T, and I don't think it should be.
Fyi, the empty_base class is there to turn multiple inheritance into a single inheritance chain (due to compiler deficiencies/object size bloat on at least Visual Studio).
I don't see why this empty_base should be templated, and it would be better suited if it wasn't since all I can think it does is make the compiler work harder. Does anyone know why it was templated to begin with? Additionally, are we safe to change empty_base to be not use templates?
It's templated so that multiple inheritance doesn't kill the empty base optimization. -- Dave Abrahams
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 };
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
On 20 Sep 2013 at 23:00, Michael Marcin wrote:
VS2012 doesn't appear to do empty base class optimization for multiple inheritance at all, so templated/untemplated also makes no difference here.
I believe the /vmm compiler flag will fix that (http://msdn.microsoft.com/en-us/library/bkb78zf3.aspx) at the cost of breaking ABI. In essence, due to backwards ABI compat constraints requiring the default /vmv option, MSVC can only collapse a single empty base class, not more than one. In other words, it's a feature not a bug :) I absolutely agree though that when they moved to 64 bit they should have fixed this. They fixed lots of long standing ABI problems with the 64 bit move, but I believe not this one sadly. Niall -- Currently unemployed and looking for work. Work Portfolio: http://careers.stackoverflow.com/nialldouglas/
participants (4)
-
Andrew Ho
-
Dave Abrahams
-
Michael Marcin
-
Niall Douglas