-2

For the following template class

template <class T> class Arbitrary {
protected:
    vector<T> ObjectArray;
public:
    Arbitrary(){}   
};

I want to be able to have a vector of base class pointers, I know I need to use an interface class but I can't get it to work, any suggestions would be greatly appreciated.

Toby
  • 19
  • 3
  • 3
    What do you mean by *"can't get it to work"*? What exactly have you tried doing, what is happening, what errors are you getting, ... – UnholySheep Apr 29 '17 at 10:45
  • I have no idea what to do, I know I want to eventually write vector name; – Toby Apr 29 '17 at 10:49
  • That can't really work since `Arbitrary` is a template type, so you can only do something like `vector*> name;` - or use something like `std::any` or `std::variant` – UnholySheep Apr 29 '17 at 10:53

1 Answers1

0

[..] I want to eventually write vector<Arbitrary*> name;

Arbitrary is a template, not a type. To "obtain" a type from it, you need to "apply" it to another type (like int). This gives you Arbitrary<int> as "result" type. This process is called template instantiation.

If you want a vector with objects of any possible type that might have been instantiated from the template Arbitrary, then you need to give them a common type (such that every object "is a" object of that common type). This is because std::vector stores only objects of a single type.

To have the objects "behave" (in the sense of having some type) differently even though they "have" a common type, you need to make them (or rather their common type) polymorphic. This is done by giving the common type some virtual function. (And since you want to delete/destruct objects through the "interface" exposed by the common type you need to make the destructor virtual!)

struct ArbitraryBase {
  // Add "common interface" functions here, as virtual
  virtual ~ArbitraryBase() = 0; // pure virtual to avoid creating objects
};
inline ArbitraryBase​::~ArbitraryBase() {}

template<typename T>
struct Arbitrary : ArbitraryBase {
  // whatever
};

Now, to actually be able to use that polymorphic property and not become victim of object slicing you need to use reference or pointer semantics:

std::vector<ArbitraryBase *> objects;

Instead of raw pointers you should consider smart pointers like std::unique_ptr<ArbitraryBase> if the objects vector should have ownership of the objects or otherwise use std::reference_wrapper<ArbitraryBase> in case lifetime of the objects is reliably handled by something else.

But if you don't add any common interface (more virtual member functions) in ArbitraryBase then you're basically reinventing std::any / boost::any. So better use those well tested implementations instead.

Daniel Jour
  • 15,896
  • 2
  • 36
  • 63
  • Thanks, i am using more virtual member functions. How do I deal with virtual member functions that are functions of T i.e virtual void function(T) – Toby Apr 29 '17 at 17:37
  • You cannot have such member functions. `T` is nothing which is "common" to all types instantiated from `Arbitrary`. Actually - assuming no template specialisations - `T` is what's different for all those types. – Daniel Jour Apr 30 '17 at 05:06