Могу ли я зарегистрировать функцию, которая вызывает конкретную функцию шаблона на основе строки, определяющей ее тип?

Я написал небольшой редактор для 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 ответ

Решение

Поскольку ваш код не будет знать внешние классы, шаблоны или что-либо другое, вам нужно будет предоставить механизм регистрации, который принимает следующее:

  1. Название типа (строка). например, "прямоугольник"
  2. Интерфейс

Интерфейс должен иметь чисто виртуальный метод 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 );
Другие вопросы по тегам