Search code examples
c++templatesinheritancepolymorphismtype-inference

Template inference when there are multiple possibilities?


I have the following pattern:

struct Wrapper
{
   vector<shared_ptr<BaseType>> data;

   template <typename DerivedType>
   add(const DerivedType& e)
   {
     data.push_back(make_shared<DerivedType>(e));
   };
}

The goal of my Wrapper is to use polymorphism, I want to be able to cast back any e to its DerivedType.

Now, if I have B, a derived class of A, and I do this:

wrapper.add(B());

The type inference could resolve DerivedType as B.

  1. Could template inference resolve DerivedType as A as well since B() has base type A even if it's not its most derived type?
  2. If yes, does make_shared<A>(e) produce a shared pointer that can be dynamically casted into shared_ptr<B>?
  3. If no, do you know a better design than my wrapper to do this? I need the wrapper to be copyable. I can just add with explicit template, but I want to avoid it.

Solution

  • Could template inference resolve DerivedType as A as well since B() has base type A even if it's not its most derived type?

    No. You would have to pass in an actual A variable to make DerivedType deduce as A, or else set DerivedType to A explicitly.

    If yes, does make_shared<A>(e) produce a shared pointer that can be dynamically casted into shared_ptr<B>?

    No. make_shared() creates exactly what you ask it to create. In this case, it would create a new A object, which is copy-constructed by slicing e into an A. As there would be no B present in the new A object, you cannot cast it later to a B.

    To make that work correctly, you would have to use make_shared<B>() to create a B object, and then assign the result to a shared_ptr<A>, which can then be later casted back to shared_ptr<B> via std::dynamic_pointer_cast.