Topic: template and inheritance


Author: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
Date: 1995/04/17
Raw View
conraud@ciril.fr (Joel Conraud) writes:

>I was surprised to get the following message both on HP and SGI
>C++ 3.x compilers :
>
>CC: "template.cc", line 25: error: cannot make a Foo <A>  from a class Foo <B>
>
>class A { ... };
>struct B : public A { ... };
>
>template <class X>
>class Foo {
...
>};
>
>As B is derived from A, I don't understand why a Foo<B> cannot be used
>when a Foo<A> is expected.

Because in general it would not be type-safe.
Suppose Foo has a member function f(X*):

 template <class X>
 class Foo {
 public:
  void f(X*) const;
 };

Now suppose you do

 int main(void) {
     A a;
     Foo<B> foo_b;
     const Foo<A>& foo_a_ref = foo_b; // 1
     foo_a_ref.f(&a);   // 2
 }

At point // 2, you are passing an A* to Foo<A>::f(A*), which should be
fine.  But the problem is that foo_b does not have an f(A*), it only
has an f(B*), and you can't pass an A* to a function expecting a B*.
So this would cause problems.

In general, a bag-of-apples is-NOT-a bag-of-fruit, even though an
apple is-A fruit.  The reason is that there are things you can do to
a bag-of-fruit that you can't do to a bag-of-apples, such as putting
an orange into the bag.

>Is this the standard behaviour ?

Yes.

--
Fergus Henderson            | As practiced by computer science, the study of
fjh@cs.mu.oz.au             | programming is an unholy mixture of mathematics,
http://www.cs.mu.oz.au/~fjh | literary criticism, and folklore. - B. A. Sheil





Author: conraud@ciril.fr (Joel Conraud)
Date: 1995/04/13
Raw View
 Hello,

I was surprised to get the following message both on HP and SGI
C++ 3.x compilers :

CC: "template.cc", line 25: error: cannot make a Foo <A>  from a class Foo <B>

with the following code :

class A {
public:
    int i;
};

struct B : public A {
public:
    int j;
};

template <class X>
class Foo {
private:
    X x_;
};

void make_something_with(const Foo<A>&) {
}

void main(void) {
    Foo<A> a_Foo_of_A;
    Foo<B> a_Foo_of_B;
    make_something_with(a_Foo_of_A);
    make_something_with(a_Foo_of_B);
    return;
}

As B is derived from A, I don't understand why a Foo<B> cannot be used
when a Foo<A> is expected.

Is this the standard behaviour ? I have not found something related
to this issue in the references I have.

 Thanks for your help,


-----
Joel CONRAUD
54501 VANDOEUVRE LES NANCY (France)
Tel : (33) 83.50.30.25
Fax : (33) 83.51.23.12
E-Mail : conraud@ensg.u-nancy.fr





Author: bflorman@indy.net (Bruce A. Florman)
Date: 1995/04/14
Raw View
: As B is derived from A, I don't understand why a Foo<B> cannot be used
: when a Foo<A> is expected.


class Animal { ... };

class Dog : public Animal { ... };

class Cat : public Animal { ... };

template <class T>
class BoxOf
{
public:
    void PutIn (T*);
    T* TakeOut ();
  ...
};

    ...
    BoxOf<Dog> aBox;
    BoxOf<Animal> & sameBox = aBox; // Dog is derived from Animal, so why not?
    Cat* aCat = new Cat;
    sameBox.PutIn(aCat); // Cat is derived from Animal, so this should work.
    Dog* aDog = aBox.TakeOut(); // Oops!
    ...

Do you see the problem?

--Bruce