Dynamic polymorphism and subclass template parameters?

N

none

I am trying to do the following (ASub and BSub are subclasses of A and B):


typedef A AType;
typedef B BType;
typedef ASub ASubType;
typedef BSub BSubType;

typedef SimpleBase<AType, BType> JobBaseType;
typedef Simple<ASubType, BSubType> JobSimpleType;
typedef std::vector<JobBaseType*> JobContainerType;


JobContainerType jobs;


// Works Fine!
JobBaseType * baseJob = new JobBaseType;
baseJob->name();


// ERROR!!
JobBaseType * simpleJob = new JobSimpleType;
simpleJob->name();





But the last initialization gives this error:


error: cannot convert ‘main()::JobSimpleType*’ to ‘main()::JobBaseType*’ in initialization

The problem is:

typedef Simple<ASubType, BSubType> JobSimpleType;

If I change this to:

typedef Simple<AType, BType> JobSimpleType;

it works.


Is there no way to create a pointer to a basetype<A,B> from a subtype<ASub, BSub> with subtype
template parameters, like:


JobBaseType * simpleJob = new JobSimpleType;

?
 
A

Anthony Delroy

I am trying to do the following (ASub and BSub are subclasses of A and B):

...

   typedef SimpleBase<AType, BType>                  JobBaseType;
   typedef Simple<ASubType, BSubType>                JobSimpleType;
...

SimpleBase<> and Simple<> are not part of the C++ Standard... unless
you show the code, how is anyone supposed to help you?

Cheers,
Tony
 
R

Robert Fendt

The problem is:

typedef Simple<ASubType, BSubType> JobSimpleType;

If I change this to:

typedef Simple<AType, BType> JobSimpleType;

it works.

Since you do not show the template definitions, I am wildly
guessing here. Thus I can give only a very general answer.

A class template is just that: a template. There is no
polymorphic relation between template instantiations with
different parameters, thus they are distinct types. I.e.,
std::vector<int> is something quite different to
std::vector<double>. Thus, if you are trying to do something
like this:

template <typename T>
class base
{
virtual void foo() = 0;
};

template <typename T>
class deriv : public base<T>
{
virtual void foo() {}
}

then you will not be able to convert a deriv<Type1_t> to a
deriv<Type2_t>, since each of them creates 'its own' special
base-class from the base template. In other words, there cannot
be any dynamic polymorphism between the two. Inheritance in this
fashion still can have its uses. E.g. in combination with
partical specialisation techniques it can help avoid code
duplication, or the base can be instantiated directly with the
derived type ('curiously recurring template pattern'). But it
just will not work the way you probably intend it to.

What you have to do is base all your derived class templates
upon a non-templated class. I.e., this should work:

class base2
{
virtual void foo() = 0;
};

template <typename T>
class deriv2 : public base2
{
virtual void foo() {}
};

You can also use a templated base, but you will have to base all
derived templates on the same instantiation (i.e., one not
depending on the current template parameters). In other words,
this should be fine too:

template <typename T>
class deriv3 : public base<int>
{
virtual void foo() {}
};


Regards,
Robert
 
R

Robert Fendt

then you will not be able to convert a deriv<Type1_t> to a
deriv<Type2_t>, since each of them creates 'its own' special
base-class from the base template. In other words, there cannot
be any dynamic polymorphism between the two. Inheritance in this

Small correction: this should of course be: one cannot convert a
deriv<Type1_t> to a base<Type2_t> if it is not exactly based upon
that type. In your code deriv<Type1_t> will probably be based
upon base<Type1_t>, thus you have two different base classes.

I just should not look at C++ problems at 7:00 in the morning...

Regards,
Robert
 
M

Michael Doubez

I am trying to do the following (ASub and BSub are subclasses of A and B):

   typedef A                                         AType;
   typedef B                                         BType;
   typedef ASub                                      ASubType;
   typedef BSub                                      BSubType;

   typedef SimpleBase<AType, BType>                  JobBaseType;
   typedef Simple<ASubType, BSubType>                JobSimpleType;
   typedef std::vector<JobBaseType*>                 JobContainerType;

   JobContainerType jobs;

   // Works Fine!
   JobBaseType * baseJob = new JobBaseType;
   baseJob->name();

   // ERROR!!
   JobBaseType * simpleJob = new JobSimpleType;
   simpleJob->name();

But the last initialization gives this error:

  error: cannot convert main()::JobSimpleType* to main()::JobBaseType* in initialization

The problem is:

   typedef Simple<ASubType, BSubType>                JobSimpleType;

If I change this to:

   typedef Simple<AType, BType>                JobSimpleType;

it works.

Is there no way to create a pointer to a basetype<A,B> from a subtype<ASub, BSub> with subtype
template parameters, like:

   JobBaseType * simpleJob = new JobSimpleType;

?

Simple<ASubType, BSubType> must inherit from SimpleBase<AType, BType>.

You can either (1) pass additional parameters to Simple<> or (2)deduce
the bases from Asub and BSub or (3)you can do both:

(1)
template<class X, class Y, class Base>
class Simple: public Base
{
// ...
};

template<class X, class Y, class XBase, class YBase>
class Simple: public SimpleBase<XBase,YBase>
{
//...
};

(2)
template<class X, class Y>
class Simple: public SimpleBase<typename X::Base,typename Y::Base>
{
//...
};

(3)
template<class X, class Y, class Base = SimpleBase<typename
X::Base,typename Y::Base> >
class Simple: public Base
{
// ...
};

// or any combination of the above
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top