1
votes

My main project class is templated class, declared with:

template<int dim, typename typ>

where dim is number of dimensions (2 or 3), and typ is floating point data type (float or double). Based on these parameters, instances of this class have their members of specific type and vectors (math) have dim number of components.

So instances can differ on member types, and their functions differ on parameter types, but they all have the same function arrangement... what can be made to run-time i.e. generically access functions of instances of this class created with different template arguments ???

1
What is the problem here? Can you give examples of how you expect to call these objects? I suspect that you don't need the method of @Tyler McHenry (it's correct, just might be overkill). I suggest to define the class with the methods and members you require, and get back to us when you have something that won't compile :-) " template<int dim, typename typ> struct X { void f(typ t); }; "Aaron McDaid

1 Answers

3
votes

This is exactly what inheritance is for. You create a common, non-template, pure-virtual base class that defines the interface used by all of your templates, e.g.:

class Base {

  public:

    virtual ~Base() {};

    virtual void foo() = 0;

    virtual int bar(int param) = 0; 

    // Etc, for whatever other methods you want
};

Then you derive your template from it:

template<int dim, typename typ>
class Dervied : public Base
{
  public:

    virtual ~Derived();

    virtual void foo();

    virtual int bar(int param); 

    // Etc, for whatever other methods you want   

  private:

    std::vector<typ> data;
};

And of course implement the methods for the Derived template. Then you can access any instantiation of Derived through a pointer or reference to Base. For example:

void callFoo(const Base& b)
{
   b.foo();
}

int main() 
{
  Derived<3,float> d_f3;
  Derived<2,double> d_d2;

  callFoo(d_f3);
  callFoo(d_d2);

  return 0;
}

It sounds from your description like there may be some methods that are in common among all instantiations of Derived, but some that are dependent on template parameters, e.g.

void addNumber(typ number);

In this case, you can't pull this function up into Base, since it wouldn't make sense to call this method on a Derived<n,float>. If there are some functions that are dependent on type and some that are dependent on the number, then you could create base classes encapsulating those ideas, like this:

class Base 
  { /* All methods independent of template parameters */ };

template <int dim> DimBase : virtual public Base
  { /* All methods dependent only on the dimension parameter */ };

template <typename typ> TypBase : virtual public Base
  { /* All methods dependent only on the type parameter */ };

template<int dim, typename typ>
  Derived : public DimBase<dim>, public TypBase<typ>
  { /* All methods */ };

This will allow you to call any independent method using a Base pointer or reference, to call any dimension-dependent method using a DimBase<n> pointer or reference, and any type-dependent method using a TypBase<T> pointer or reference.

Note that in the above, it is advisable that Base, TypBase and DimBase all be abstract classes (containing at least one unimplemented virtual method), and it is essential that TypBase and DimBase inherit from Base using virtual public instead of just public, otherwise you get the "dreaded diamond"