У меня сложный вопрос о шаблонных классах C ++ (11) и об их создании с типами, определенными во время выполнения:
Следующий сценарий:
Пользователь определяет тип класса шаблона, используя файл конфигурации (параметры ROS). Это определяет только тип класса шаблона, а не дальнейшую логику:
Определение класса:
template<typename T>
class MyClass {
//[...]
}
Примерный код:
/* [Read parameter and write result to bool use_int] */
std::unique_ptr<MyClass> myclassptr {nullptr};
if(use_int) {
myclassptr.reset(MyClass<int>);
} else {
myclassptr.reset(MyClass<double>);
}
myclassptr->foobar();
/* [more code making use of myclassptr] */
Поэтому этот код (конечно) не компилируется, потому что шаблон unique_ptr должен быть указан также с типом шаблона. Однако тогда возникает проблема, что тип шаблона должен быть одинаковым для всех объектов, назначенных с использованием reset
,
Одним уродливым решением было бы скопировать код myclassptr->foobar();
и следующее в каждую ветку if / else, что мне действительно не нравится.
Я хотел бы увидеть решение, подобное этому:
/* [Read parameter and write result to bool use_int] */
MyClass<use_int ? int : double> myclass;
myclass.foobar();
До сих пор я читал, что что-то подобное также невозможно.
У кого-нибудь есть хорошее решение для этого?
Самый простой способ сделать это:
class IClass{
virtual ~IClass {}
virtual void foobar()=0;
};
template<typename T>
class MyClass:public IClass {
public:
void foobar() override {
// code here
}
};
std::unique_ptr<IClass> myclassptr {};
if(use_int) {
myclassptr.reset(new MyClass<int>());
} else {
myclassptr.reset(new MyClass<double>());
}
myclassptr->foobar();
boost::variant
было бы другим решением, но обычно используется для несвязанных типов. Стирание типов может быть выполнено, но, опять же, это обычно делается, когда у вас есть несвязанные типы, на которые вы хотите наложить единый интерфейс.
На других языках дженерики выглядят как template
s, но на самом деле это абстрактный интерфейс с автоматически генерируемыми типами и добавлением некоторой проверки типов. C ++ template
s — фабрики времени компиляции функции или класса. Два выхода таких фабрик по умолчанию не связаны во время выполнения, и вы можете добавить такие отношения, если хотите.
В зависимости от того, что вы хотите, вы можете сделать MyClass типом варианта, который содержит int или double, или вы можете использовать стирание типа, чтобы скрыть реализацию за интерфейсом. Boost.Variant Библиотека может помочь реализовать первое.