Re: [eigen] Question about the class hierarchy |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/eigen Archives
]
- To: eigen@xxxxxxxxxxxxxxxxxxx
- Subject: Re: [eigen] Question about the class hierarchy
- From: Manoj Rajagopalan <rmanoj@xxxxxxxxx>
- Date: Wed, 30 Jun 2010 10:53:20 -0400
- Organization: EECS Dept., University of Michigan, Ann Arbor, MI, USA
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;
}