Re: [eigen] Question about the class hierarchy

[ Thread Index | Date Index | More lists.tuxfamily.org/eigen Archives ]




On Wednesday 30 June 2010 04:28:04 am Hauke Heibel wrote:
> We try hard to prevent multiple-inheritance since we have encountered
> examples where MSVC fails to perform empty base class optimization
> which is crucial for our fixed size types.

==== Ouch! So microsoft had to continue getting in the way ...

>
> > 3.   If the Array base and Matrix base must inherit EigenBase then this
> > inheritance must be virtual so that there is exactly one copy of
> > EigenBase in the derived object. virtual inheritance works with templates
> > at least with gcc 4.2 on my linux machine.
>
> I don't quite understand this? The EigenBase has zero size. No
> members, no virtual functions. Having even a single virtual function
> in EigenBase is not an option because of the sizeof constraint I told
> you about before.
>

Oh, I didn't mean virtual functions - I just meant using the "virtual" keyword 
in the inheritance spec just following the class name in its declaration. 
This is explained here:
http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.8

In Eigen's case, EigenBase is at the top of the dreaded diamond. ArrayBase and 
MatrixBase both inherit it. If we hypothetically consider the simplified 
multiple-inheritance picture of a dense matrix that I enquired about, then 
these declarations would look like:

  class ArrayBase : public virtual EigenBase {...};
  class MatrixBase : public virtual EigenBase {...};

Then (dense) Matrix would inherit both the usual way, without the "virtual" 
keyword. The "virtual" in the above decls ensures that only one copy of 
EigenBase is made in Matrix but the latter's CTOR will have to call the 
EigenBase CTOR directly even though the inheritance is indirect.

But virtual inheritance does create space overheads so it may not be suitable 
for the reason you mentioned even if there are no virtual functions. I am 
attaching an experiment program with the dreaded diamond inheritance. the top 
base class just wraps in int. The sizeof() outputs show that 4 bytes are 
added with each layer of virtual inheritance but this is not so with regular 
inheritance.

With virtual inheritance:
sizeof(int) = 4
sizeof(A<int>) = 4
sizeof(B<int>) = 8
sizeof(C<int>) = 8
sizeof(D<int>) = 12


Without vitual inheritance:
sizeof(int) = 4
sizeof(A<int>) = 4
sizeof(B<int>) = 4
sizeof(C<int>) = 4
sizeof(D<int>) = 8


Thanks,
Manoj
#include <iostream>

using namespace std;


template<typename T>
class A
{
public:
	A() {}
	A(T const& _t) : t_(_t) {}
	~A() {}
	T get() const { return t_; }
protected:
	T t_;
};


template<typename T>
class B : public virtual A<T>
{
public:
	B() {}
	B(T const& _t) : A<T>(_t) {}
	~B() {}
	T get() const { return (this->t_+1); }
};


template<typename T>
class C : public virtual A<T>
{
public:
	C() {}
	C(T const& _t) : A<T>(_t) {}
	~C() {}
	T get() const { return (this->t_-1); }
};


template<typename T>
class D : public B<T>, public C<T>
{
public:
	D(T const& _t) : B<T>(_t), C<T>(_t) {}
	~D() {}
	T get() const { return (A<T>::t_*10); }
};


int main(void)
{
	D<int> d(5);
	cout << "d contains " << d.get() << endl; // =50
	cout << "sizeof(int) = " << sizeof(int) << endl;
	cout << "sizeof(A<int>) = " << sizeof(A<int>) << endl;
	cout << "sizeof(B<int>) = " << sizeof(B<int>) << endl;
	cout << "sizeof(C<int>) = " << sizeof(C<int>) << endl;
	cout << "sizeof(D<int>) = " << sizeof(D<int>) << endl;
	return 0;
}



Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/