Упрощенная у меня есть следующие иерархии классов:Избегайте включения шаблона параметров
class BaseVec {
public:
BaseVec() {};
virtual ~BaseVec() {};
virtual double get_double(int i) const = 0;
};
template<typename T>
class Vec : public BaseVec {
public:
Vec() { ... };
~Vec() { ... };
T get(int i) const { ... };
double get_double(int i) const {
return get(i);
};
};
В моем проекте я неоднократно в конечном итоге с кодом следующего вида:
template<typename T>
double foo_template(void* p) {
Vec<T>* v = reinterpret_cast<Vec<T>*>(p);
// use v which involves calling get
return result;
}
double foo(void* p, int type) {
if (type == 0) {
return foo_template<double>(p);
} else if (type == 1) {
return foo_template<int>(p);
} else if (...) {
// etc.
} else {
//unsupported type
}
}
(я мог бы использовать переключатель и использовать перечисления или первый лить p
до BaseVec
, а затем сделать dynamic_cast
с, но логика остается неизменной)
Это не идея l поддерживать. Например, когда я добавляю дополнительный класс, который я хочу поддержать, я должен добавить предложение к каждому из блоков if-else-if.
Одним из возможных способов упрощения этого метода было бы лить p
на BaseVec*
и использовать метод get_double
. Однако, поскольку этот метод называется очень часто, это приводит к низкой производительности. Кроме того, это не всегда возможно: иногда я хочу вызвать метод get
, поскольку возвращаемый тип важен.
Я экспериментировал с шаблоном посетителя, и хотя у этого есть некоторые преимущества, это все равно означает, что я должен написать отдельный фрагмент кода для каждого возможного параметра шаблона.
Есть ли способ сделать этот код более удобным для обслуживания?
PS: У меня нет (много) контроля над тем, что приходит в foo
. foo
вызывается внешней программой (точнее, R). Поэтому я могу передавать общие указатели, int, double и векторы символов до foo
.
PPS: Предложения по улучшению названия также приветствуются.
Спасибо. Это было бы лучше. Однако, как я сказал в своем PS, у меня мало влияния на то, что точно передается 'foo'. Этот код окажется в библиотеке, которая вызывается другой программой (точнее, R). Эта программа не знает о 'Vec', поэтому я получаю некоторый общий указатель, который я должен использовать для правильного типа. –
Обновленный вопрос, чтобы отразить предыдущий комментарий. –