Roland Soós
Roland Soós

Reputation: 3280

C++ template casting on derived classes

I have 3 class which derived from each other:

class Basic{
...
}

class Extended : public Basic{
...
}

class Full : public Extended{
...
}

I have a template class which holds 5-5 from this classes:

template <class T>
    class group{
    public:
             ...
    private:
        T one, two, three, four, five;
    };

group<Basic> basicGroup;
group<Extended> extendedGroup;
group<Full> fullGroup;

Can I easily cast for example fullGroup to basicGroup or extendedGroup to basicGroup? (I just want to cast upward)

Upvotes: 4

Views: 4679

Answers (6)

CashCow
CashCow

Reputation: 31435

Most of the time you don't want to dynamic cast and don't care what type you have underneath. You have an operation you want to perform polymorphically on your base class and you just call it.

Note however though that your group template contains instances of the class, not pointers / shared-pointers to them. Thus you can't add a Full or Extended to a group of a lesser class without slicing it.

Upvotes: 0

Bj&#246;rn Pollex
Bj&#246;rn Pollex

Reputation: 76778

A solution would be to create a kind of view-class that can wrap a group, and exposes the individual objects as base-class instances:

template <class T>
class group{
public:
    const T & getOne() { return one; }
private:
    T one, two, three, four, five;
};

template <class T, U>
class group_view {
public:
    group_view(group<T> & inner) : innerGroup(inner) {}

    const U & getOne() { return dynamic_cast< const U &>(one); }
private:
    group<T> & innerGroup;
};

You could use it like this:

group<Full> fullGroup;
group_view<Full, Extended> extendedGroupView(fullGroup);

If you extract the public interface of group into an abstract base class, you can even use group_views polymorphically.

Upvotes: 3

Charles Salvia
Charles Salvia

Reputation: 53289

A class template with a different parameter is considered by the C++ type system to be an entirely different type. So, a group<Basic> is not the same type as a group<Extended>, and you cannot safely cast between these two types.

You can only cast upward on individual instances of Full or Extended.

Upvotes: 0

Jean-Marc Valin
Jean-Marc Valin

Reputation: 300

You cannot directly cast groups like this. What you need to do is either

  1. do a generic group class with one-five being pointers to Basic
  2. Make FullGroup derive from ExtendedGroup, which would derive from basicGroup.

Upvotes: 0

Gorpik
Gorpik

Reputation: 11028

No, these three types are unrelated, you cannot cast between them.

A good example to understand why is: imagine you have a std::list<Dog>, where Dog inherits from Animal. You may thing it would be natural to consider that the std::list<Dog> can be cast into a std::list<Animal>; but what would happen with this code?

std::list<Dog> dogList;
// ... fill dogList as appropriate
std::list<Animal> animalList = dogList; // Should this be legal?
Animal aml = animalList.get(); // Fine; you get a Dog, which is an Animal
animalList.insert(Cat()); // Aww: you are trying to add a Cat to a Dog list!

Upvotes: 3

peoro
peoro

Reputation: 26060

You can't cast a container of one type to a container of another type. And in this case group is basically a container...

You need to copy one by one elements.

Upvotes: 0

Related Questions