Могу ли я зарегистрировать функцию, которая вызывает конкретную функцию шаблона на основе строки, определяющей ее тип?
Я написал небольшой редактор для Qt. Он принимает указатель и в зависимости от типа атрибута (определяется строкой) извлекает из него данные с использованием шаблонной функции.
(Например, если тип "точка", он будет вызывать getBoundValue<QPoint3>
на указатель.)
Это прекрасно работает на практике. Но я настраиваю ее как библиотеку, чтобы другие могли ее использовать, и я предполагаю, что они захотят добавить поддержку других типов. Проблема в том, что я не хочу, чтобы им приходилось изменять исходный код, а либо наследовал от класса, либо регистрировал обратные вызовы для новых типов. Я не знаю, как бы я реализовал последний вариант, так как я не мог передать строковый тип и тип класса вместе, не так ли?
Если я хочу разрешить пользователям добавлять поддержку для своих собственных типов, придется ли им реализовывать подкласс моего редактора атрибутов, который обрабатывает эти значения? Или есть способ, которым я мог бы реорганизовать свой код, чтобы пользователи могли передать функциональность для обработки нового типа, такого как "прямоугольник", и типа Rectangle, который вызывает getBoundValue<Rectangle>()
?
Вот пример кода, где я вижу, имеет ли объект определенный тип. Если это так, я вызываю соответствующую функцию шаблона:
AttributeEditor::update(Bindable* instance) {
_instance = instance;
clear();
for (int i = 0; i < _instance->attributeCount(); i++) {
Attribute attr = _instance->at(i);
QList<QStandardItem*> attributeRow;
QStandardItem* nameItem = new QStandardItem(
attribute->property("name").toString()
);
attributeRow << nameItem;
QList< QList<QStandardItem*> > subRows;
if (attr->property("getter").isValid()) {
std::cout << attr->type().toStdString() << std::endl;
QString value = "?";
if (attr->type() == "point3" || attr->type() == "vector3") {
QVector3D p = getBoundValue<QVector3D>(_instance, attr);
/* ... */
}
/* ... */
}
1 ответ
Поскольку ваш код не будет знать внешние классы, шаблоны или что-либо другое, вам нужно будет предоставить механизм регистрации, который принимает следующее:
- Название типа (строка). например, "прямоугольник"
- Интерфейс
Интерфейс должен иметь чисто виртуальный метод getBoundValue
, Все классы, которым нужна функциональность, должны реализовывать интерфейс.
Пример:
struct IShape {
virtual QVector3D getBoundValue() = 0;
// more shape methods
...
};
class Rectangle {
QVector3D getBoundValue();
};
// register interface prototype - exported from your library
void RegisterShape( IShape* pShape, const QString& name );