4

If I have a template class, that I want to instantiate with different data types:

template <typename T>
class A {
  T value;
  // ...
};

And I also want to use the objects of this class in a Standard Template Library container (say vector).

In my understanding creating a vector of A objects would not be accepted by the compiler, because A<int> and A<char> are actually different types and I can't put them in the same vector.

The workaround I found was creating a base class, a derived template class, and a vector of base class pointers.

class ABase {
  // ...
};

template <typename T>
class ADerived : public ABase{
  T value;
  // ...
};

std::vector<BaseA*> mySuperVector;

I am starting to experiment with templates to gain a better understanding and I am wondering whether there are better solutions for this. My workaround above gives me also headache, because I am afraid that typecasting will be inevitable at some point.

lulijeta
  • 900
  • 1
  • 9
  • 19

2 Answers2

3

Templates are a compile-time code generation construct. If you need an heterogeneous container of objects at compile-time, then you can use std::tuple:

std::tuple my_tuple{A<int>{}, A<char>{}, A<double>{}};

If you need an heterogeneous container of objects at run-time, you do need some sort of polymorphism. Using a base class with virtual methods is a valid option. If you know all the possible choice of types your object can be in advance, you can also use std::variant:

using my_a = std::variant<A<int>, A<char>, A<double>>;
std::vector<my_a> vec;

In this case, my_a can either be A<int>, A<char>, or A<double> at any given time. The active alternative can change at run-time.

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
2

Needing to typecast to the derived type is not related to the derived type being the instantiation of a class template, it's a design issue. Maybe you need virtual functions or multiple containers instead.

Otherwise, your solution is fine, but do switch to std::unique_ptr if the container is supposed to own the contained objects.

Quentin
  • 62,093
  • 7
  • 131
  • 191
  • You are absolutely right about typecasting being a design issue. I don't have it yet but it feels wrong, because the inheritance is a forced one so that I can put my template classes in the same container. The forced design for workarounds usually leads to design issues. Also adding an extra layer of inheritance seems like being wasteful. (I am working on embedded systems) – lulijeta Oct 30 '18 at 11:07
  • @lulijeta you put objects together in an homogeneous container based on the supposition that they can be processed in the same way for what you need. If that's not the case, then a single container doesn't cut it. – Quentin Oct 30 '18 at 11:12
  • I guess you are right. They can definitely be processed the same way. – lulijeta Oct 30 '18 at 11:13