Question: Assume I have the following 2 classes `Super` and `Deriv` where `Deriv` is a subclass of `Super`.

`Super` and `Deriv` are both templated classes. I want to create a `vector` of type `Super<?>`. Where the `?` signifies any type. Currently I have come up with this:

```
#include <iostream>
#include <vector>

template <typename T>
class Super {
public:
    T val;
    Super(T val) : val(val) {};
};

template <typename T>
class Deriv : public Super<T> {
public:
    Deriv(T val) : Super<T>(val) {};
};

int main() {
    std::vector<Super*> a;
    a.push_back(new Deriv<int>(1));
    a.push_back(new Deriv<float>(1.0f));

    std::cout << a[0]->val << std::endl;
    return 0;
}

```

Of course this does not work because `std::vector<Super*>` needs a template type like `std::vector<Super<int>*>`. However the problem with this is I can only add items to the vector of type `Super<int>*` and not `Super<float>*`.

How can I alter this code to allow me to add a `Super` type or it's derivatives to a vector which has any template type like `int`, `float`, `short` etc?

Answer: 
This

```
std::vector<Super*> a;

```

Is wrong.

There is no type named `Super` in your code. Yes, you declared something named "Super", but it's not a class, it's a class template.

The name of the feature says it all. It's a template. The compiler will use `Super` to generate new types at compile time.

For example, `Super<int>` Refer to the class generated by the compiler when filling the hole `T` in the `Super` template.

So why `a[0]->val` cannot possibly work? Well, imagine this:

```
template<>
struct Super<std::string> {
    std::string my_val;
};

```

We specialize `Super` so when instantiated with `std::string`, it no longer have the `val` member, but the `my_val` member.

Now, what do you expect this code to do?

```
std::vector<Super*> a;
a.push_back(new Deriv<std::string>);

std::cout << a[0]->val << std::endl;

```

Quite puzzling isn't it? You'd need a compilation error at runtime. Since the existence (or non existence) of variable is determined at compile time, it's not possible.

---

Now how can we solve your problem?

In your case, it would be as simple as adding an interface above `Super`, and exposing functions that implements behaviors needed to do your calculations:

```
struct Interface {
    void print(std::ostream) const = 0;
    bool lessThan(double) const = 0;
};

template <typename T>
struct Super : Interface {
    T val;

    Super(T val_) : val{val_} {};

    // We implement the needed behavior.
    void print(std::ostream o) const override {
        o << val << std::endl;
    }

    // Example of calculation
    bool lessThan(double rhs) const override {
        return val < rhs;
    }
};

```

Now you can do:

```
std::vector<Interface*> a;

// ...

a[0]->print(std::cout);
a[0]->lessThan(3.7);

```
C++ does not have the feature you are asking for (I believe it is a kind of reification). This means you cannot store arbitrary types in location one, then specify arbitrary operations in a completely unrelated source file in location two, then apply the operations to the data in location three.

There are many problems you can solve that are close to what you are asking for: Restrict what operations you want to do at location two, *or* restrict what types you store at location one, and the problem can be solved. Alternatively, restrict what type x operation pairs you support at location three.

Note that composition of the restricted set of operations can also work.

In theory you can embed a full compiler or interpreter in a C++ binary, compile code and dynamically load it. (This is basically how C#/Java manage reification). This is rather impractical for most problems. The language provides no support for this, but this is C++, you can do anything (write a Java/C# compiler even).

With no information about the underlying problem you need to solve, I cannot tell you which of the above is the correct approach.

This is the reason why "if I had X I coukd solve Y, but I cannot figure out X. I know, I'll just ask stack overflow how to do X!" is known as an X/Y problem. We can probably solve Y, but you asked about X which woukd solve Y without even describing Y. Feel free to post the Y problem and ask about it. Use the [ask a question] button above.

---

Restrict what types you handle at storage:

Store a `std::variant`. Use `std::visit`. Or write your own or use `boost::variant`.

---

Restrict what operations to perform:

Use type erasure to generate the per-type operation when you store the type.

---

Restrict the operation-type pairs at point of call:

Use RTTI to exctract what type is stored, have a large switch switch that then uses solution one.