Array of template objects

I do not know how to solve the problem with templates and inheritance.

My code has a template class that looks something like this:

template<typename T> class Derived : public Base{ T value; public: Derived(T arg) { value=arg; }; T getValue() { return value;}; }; class Base{ }; 

The only purpose of my base class is to group an array of Derived class objects. The T parameter is usually double, float, or complex, although int and struct can also be useful. (Subsequently, there should be several more similar derived classes with several additional functions.)

I can create such a group

 Base** M = new Base*[numElements]; 

and assign them elements of a derived class, for example:

 M[54] = new Derived<double>(100.); 

But how can I find out that the 55th element has a value of 100 later? I need something like

 virtual T getValue() = 0; 

but T is the name of the derived class and may be different for any two elements of this array.

+4
source share
6 answers

The Visitor template is probably the best choice here. The code that iterates through the array must provide a Visitor object that knows how to handle each of the different types.

 struct NumericVisitor { virtual void visit(double) = 0; virtual void visit(int) = 0; virtual void visit(unsigned char) = 0; }; struct Visitable { virtual void visitValue(NumericVisitor& visitor) = 0; }; template<typename T> class Derived : public Visitable { T value; public: Derived(const T& arg) value(arg) {} void visitValue(NumericVisitor& visitor) { visitor.visit(value); } }; 

Now you can define visitors for each operation that you want to do in the collection, for example. convert each element to a string, with a different format for each type, or store each element in a file, where each type can occupy a different space.

+4
source

You can add overloaded has_value() methods to the Base class:

 class Base { public: virtual ~Base () {} virtual bool has_value (int i) {return false;} virtual bool has_value (double d) {return false;} virtual bool has_value (const std::string& s) {return false;} // etc. }; 

one of which you will override in the Derived class:

 template<typename T> class Derived : public Base { T value; public: Derived(T arg) {value=arg;} T getValue() { return value;} virtual bool has_value (T t) { return t == value; } }; 

eg:.

 bool test () { std::vector<Base*> bases; bases.push_back (new Derived<double> (1.234)); bases.push_back (new Derived<int> (100)); bases.push_back (new Derived<std::string> ("zap")); for(std::vector<Base*>::const_iterator iter = bases.begin (); iter != bases.end (); ++iter) if ((*iter)->has_value (100)) return true; return false; } 

Please note: you cannot replace the has_value methods in the base class with one template method, since you cannot use template virtual methods.

+2
source

Add the getDouble method to the base class. Then, derived classes must implement this method and, if necessary, use their own type.

0
source

You can use dynamic_cast to find out what type it is (in addition to what @StackedCrooked says). This will require some virtual functions defined in the base class, but you already need a virtual destructor (to be able to delete values ​​using the base class pointers).

Alternatively, you can try boost :: variant or boost :: any :)

0
source

NO. It is impossible to practically implement such a function for two reasons:

  • Base cannot be a template, since you want the common descriptor to save an array that can contain any type of Derived like <int>, <double>, <float>, any struct <abc> .
  • You cannot have a template virtual method inside Base , because the language does not allow this

The usual simple way to solve this problem is to have a getter method for each type of type get_double() , get_int() , get_float() , get_abc() , etc. However, your Base will be cluttered with such methods.

0
source

use boost :: any to store objects in an array. Then, when you want to work with it, you can use boost :: any_cast for the possible types that you have.

0
source

All Articles