В настоящее время я пытаюсь реализовать проверку типов по универсальному параметру, и я понятия не имею, возможно ли это как-то без перегрузки функций и методов, возможности, которую я хотел бы избежать. Я постараюсь объяснить, что я пытаюсь сделать ниже.
У меня есть класс Algorithm
, который используется в качестве базы для описания нескольких алгоритмов. Каждый из них может иметь свои конкретные параметры в качестве входа и выхода. Я мог бы перегрузить основной метод Run
, но мне пришлось бы делать это для любого нужного мне типа, который может быстро стать длинным списком. Поэтому я решил попробовать сделать что-то вроде этого:
class Algorithm {
public:
Algorithm();
GenericParameter* Run(GenericParameter* input);
};
class Alg0 : public Algorithm { ... };
class Alg1 : public Algorithm { ... };
class Alg2 : public Algorithm { ... };
GenericParameter
является специализированным типом и основан на двух основных классах, шаблонном TParam
классе, который не может быть изменен. Идея в том, что каждая специализация TParam
наследует класс GenericParameter
:
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;
};
Используя статические методы Create
и Get
, я могу легко создавать любые параметры, предположив, что я специализировал связанный класс TParam
.
Я использовал его, он работает, предполагая, что вы знаете, какой тип у вас есть в качестве входных данных, и вы должны вернуться в Algorithm
унаследованных классах. Но одна вещь беспокоит меня в том факте, что приведенный ниже код компилируется и запускается:
TypeA aobj();
GenericParameter* aobj_p = GenericParameter::Create(aobj);
TypeB bobj = GenericParameter::Get<TypeB>(aobj_p);
Поскольку я не проверяю тип, я могу получить объект TypeB
из экземпляра GenericParameter
, пока он оборачивает объект TypeA
. Я пробовал решение для проверки типов, основанное на перечислении и поле типа в классе GenericParameter
, но я хотел бы знать, видит ли кто-нибудь другую возможность для этого.
Я могу обеспечить реализацию методов, если кто-то захочет.