vendredi 31 mai 2019

Handle generic parameter with type checking

I am currently trying to implement a type checking over a generic parameter and I have no idea if this is somehow possible without overloading functions and methods, a possibility I would like to avoid. I will try to explain what I'm trying to do below.

I have a class Algorithm that is used as a base to describe several algorithms. Each of them can have their specific parameters as input and output. I could overload the main Run method but I would have to do it for any type I need which can quickly become a long list. So I decided to try doing something like this:

class Algorithm {
public:
  Algorithm();

  GenericParameter* Run(GenericParameter* input);
};

class Alg0 : public Algorithm { ... };
class Alg1 : public Algorithm { ... };
class Alg2 : public Algorithm { ... };

The GenericParameter is type specialized and based on two main classes, a templated TParam class that is uninstanciable. The idea being each specialization of TParam inherits the GenericParameter class:

template <typename T>
class TParam {
public:
  TParam() {
    throw std::runtime_error("Cannot instanciate this object");
  }
  TParam(const T& elmt) {
    throw std::runtime_error("Cannot instanciate this object");
  }
};

class GenericParameter {
protected:
  GenericParameter();
  virtual ~GenericParameter();

  // To create a TParam<T> instance. 
  // Will fail if no specialization.
  template <typename T>
  static GenericParameter* Create(const T& elmt) {
    return new TParam<T>(elmt);
  }
  // To create a TParam<T> instance. 
  // Will fail if no specialization
  template <typename T>
  static GenericParameter* Create() {
    return new TParam<T>();
  }
  // To get the object in the TParam<T> param
  template <typename T>
  static T& Get(GenericParameter* param) {
    TParam<T>* tmp = static_cast<TParam<T>* >(param);
    return tmp->object;
  }
};

template <>
class TParam<TypeA> : public GenericParameter {
public:
  TParam<TypeA>() {};
  TParam<TypeA>(const TypeA& elmt): object(elmt) {};
  TypeA object;
};

template <>
class TParam<TypeB> : public GenericParameter {
public:
  TParam<TypeB>() {};
  TParam<TypeB>(const TypeB& elmt): object(elmt) {};
  TypeB object;
};

Using the Create and Get static methods, I can easily create all kind of parameters, supposing I have specialized the related TParam class.

I used it, it works assuming you know what type you have as input and you should return in the Algorithm inherited classes. But one thing bothers me in the fact the code below compiles and runs:

TypeA aobj();
GenericParameter* aobj_p = GenericParameter::Create(aobj);
TypeB bobj = GenericParameter::Get<TypeB>(aobj_p);

Since I don't do type checking, I can get a TypeB object from a GenericParameter instance while it wraps a TypeA object. I have tried a type checking solution based on an enumeration and a type field in the GenericParameter class but I would like to know if anyone see another possibility for it.

I can provide the implementation of the methods if someone wants it.

Aucun commentaire:

Enregistrer un commentaire