Search code examples
c++classdowncast

Downcasting `vector<Parent>`


I have a problem with upcasting and downcasting in my program. I have a vector<Child> that is passed to a function that expects const vector<Parent>& pp. There are no problems up to here (EDIT: apparently there are! See the comments). But, now I want to pass pp to a function that expects const vector<Child>& cc, Which I cannot do.

How should I do this, while at the same time I do not give the functions the ability to modify the original classes? Could you list various ways of doing this, preferably with their pros and cons?


Solution

  • There is a thing called variation. It comes in a 3 flavors:

    • invariation - even though B extends A, T<B> not extends T<A>,
    • covariation - when B extends A, then T<B> extends T<A>,
    • contravariation - when B extends A, then T<A> extends T<B>.

    When it comes to C++ templates you end up with invariation. Even though by name it looks the same: vector<Parent> and vector<Child> those are 2 different types.

    If you look at what is generated by compiler both of them operate on types which could potentially have different sizes. Since C++ rely on knowledge on object size (e.g. when it calculates position of object in an array) type e.g. Child[] cannot be casted to Parent[] because position of some object might be miscalculated. For the same reasons templates act in an invariant way: compiler cannot guess when it would and when it wouldn't be safe to perform such casting.

    So it is up to you fix that and you have some options here. One would be making function that take that parameter template as well:

    template<T>
    void performAction(vector<T> objects) {
      // ...
    }
    

    Other would be replacing values with a (smart) pointers - they would handle polymorphism easily.

    EDIT:

    To specify what I meant in the last sentence: you could simply use vector< unique_ptr<Parent> > or vector< shared_ptr<Parent> > to store any instance of Parent (including Child), so you won't have to perform any casting of the container.