Davide
Davide

Reputation: 525

How to mimic polymorphism in classes with template methods (c++)?

in the problem i am facing i need something which works more or less like a polymorphic class, but which would allow for virtual template methods.

the point is, i would like to create an array of subproblems, each one being solved by a different technique implemented in a different class, but holding the same interface, then pass a set of parameters (which are functions/functors - this is where templates jump up) to all the subproblems and get back a solution.

if the parameters would be, e.g., ints, this would be something like:

struct subproblem
{
...
virtual void solve (double& solution, double parameter)=0; 
}
struct subproblem0: public subproblem
{
...
virtual void solve (double& solution, double parameter){...}; 
}
struct subproblem1: public subproblem
{
...
virtual void solve (double* solution, double parameter){...}; 
}

int main{
subproblem problem[2];
subproblem[0] = new subproblem0();
subproblem[1] = new subproblem1();
double argument0(0),
       argument1(1),
       sol0[2],
       sol1[2];
for(unsigned int i(0);i<2;++i)
    {
    problem[i]->solve( &(sol0[i]) , argument0);
    problem[i]->solve( &(sol1[i]) , argument1);
    }
return 0;
}

but the problem is, i need the arguments to be something like

Arg<T1,T2> argument0(f1,f2)

and thus the solve method to be something of the likes of

template<T1,T2> solve (double* solution, Arg<T1,T2> parameter)

which cant obviously be declared virtual ( so cant be called from a pointer to the base class)...

now i'm pretty stuck and don't know how to procede...

Upvotes: 2

Views: 715

Answers (2)

Mikael Persson
Mikael Persson

Reputation: 18562

Typically, this type of problem is solved with a public function template and a protected virtual function taking in a type-erasure object. For your specific problem, this could translate into this:

struct param_list_base {
  virtual double getParam(int i) const = 0;
};

template <typename ParamStorage>
struct param_list : param_list_base {
  const ParamStorage& params;
  param_list(const ParamStorage& aParams) : params(aParams) { };
  virtual double getParam(int i) const {
    return params[i];
  };
};

class subproblem {
  protected:
    virtual void solve_impl(double* sol, param_list_base* params) = 0;
  public:
    template <typename ParamStorage>
    void solve(double* sol, ParamStorage params) {
      param_list<ParamStorage> tmp(params);
      solve_impl(sol, &tmp);
    };
};

And then, you can also specialize the param_list template for different kinds of parameter storage objects. For functors, you can do the same. This is, of course, somewhat limited, but it usually can be made to work in most cases. Otherwise, you can still rely on a similar pattern of protected versus public functions. For example, you can have a set of non-template virtual functions in the public interface, which all just call a private function template (one implementation for all the cases), this isn't pretty but it works if the number of possible template arguments is limited.

Upvotes: 1

Alex Brown
Alex Brown

Reputation: 42872

Declare an abstract base class, and have your templates inherit from that.

Upvotes: 0

Related Questions