Naibaf Naibaf - 3 months ago 10
C++ Question

C++ templates and casting with base and sub class as template parameter

Sorry for the confusing title. I am not sure how to describe my problem better.

Please look at the following code:

template<class T>
class TmpClass
{};

class Base
{};

class Child : public Base
{};

int main()
{
typedef TmpClass<Base*> A;
typedef TmpClass<Child*> B;

A a;
B b;
A* ap = &b; //this does not work
}


Why is the cast not working although the template parameter is derived?

Answer

Because it generates 2 different classes. Lets assume the following:

template<class T>
struct TmpClass
{
    T t;
    double d;
};

struct Base
{
    int i;
};

struct Child : public Base
{
    int i2;
};

This is really basic and would even be more cluttered with virtual functions etc. This is just simplified for a possible issue which can occur.

When you now instantiate the classes they look like this (the names are completely made up by me)

struct _internal_TmpClass_Base
{
    Base t;
    double d;
};

struct _internal_TmpClass_Child
{
    Child t;
    double d;
};

Thing is:

The size of Base is sizeof(int). The size of Child is 2*sizeof(int)

If you want to access d in TmpClass, it is (depending on the template) at complete different memory locations. A TmpClass<Child> has d at the location after the size of Child (2*int). When you now cast it to a TmpClass<Base> and you want to access d it assumes this is in the memory after the size of Base (1*int) not Child. And you will read or write memory which you don't intent.

Those things are usually categorized as "Undefined Behavior"