Я разрабатываю приложение приобретения научных данных с помощью QT, Так как я не глубокий эксперт в QT, я хотел бы некоторую архитектуру, консультируют от сообщества по вопросам следующей проблемы:
Поддержка приложений несколько интерфейсов приобретения оборудования, но я хотел бы обеспечить общий API сверху тех интерфейсов. Каждый интерфейс имеет демонстрационный тип данных и единицы для его данных. Таким образом, я представляю вектор образцов от каждого устройства как a std::vector
из Повышения. Количества единиц (т.е. std::vector<boost::units::quantity<unit,sample_type> >
). Я хотел бы использовать многоадресную архитектуру стиля, где каждый источник данных широковещательные сообщения недавно получил данные к 1 или более заинтересованные стороны. Механизм Сигнала/Слота QT является очевидным пригодным для этого стиля. Так, я хотел бы, чтобы каждый источник данных испустил сигнал как
typedef std::vector<boost::units::quantity<unit,sample_type> > SampleVector
signals:
void samplesAcquired(SampleVector sampleVector);
для единицы и sample_type подходящий для того устройства. Так как шаблонный QObject
подклассы не поддерживаются компилятором метаобъекта, кажется, нет способа иметь (шаблонный) базовый класс для всех источников данных, который определяет samplesAcquired
Сигнал. Другими словами, следующее не будет работать:
template<T,U> //sample type and units
class DataSource : public QObject {
Q_OBJECT
...
public:
typedef std::vector<boost::units::quantity<U,T> > SampleVector
signals:
void samplesAcquired(SampleVector sampleVector);
};
Наилучшим вариантом, который я смог придумать, является двухмногоуровневый подход:
template<T,U> //sample type and units
class IAcquiredSamples {
public:
typedef std::vector<boost::units::quantity<U,T> > SampleVector
virtual shared_ptr<SampleVector> acquiredData(TimeStamp ts, unsigned long nsamples);
};
class DataSource : public QObject {
...
signals:
void samplesAcquired(TimeStamp ts, unsigned long nsamples);
};
samplesAcquired
сигнал теперь дает метку времени и количество образцов для приобретения, и клиенты должны использовать IAcquiredSamples
API для получения тех образцов. Очевидно источники данных должны разделить на подклассы и DataSource и IAcquiredSamples
.
Недостаток этого подхода, кажется, потеря простоты в API... было бы намного более хорошо, если клиенты могли бы получить полученные образцы в соединенном Слоте. Способность использовать соединения QT с очередями также сделала бы проблемы поточной обработки легче вместо того, чтобы иметь необходимость управлять ими в acquiredData
метод в каждом подклассе.
Еще одна возможность, должен использовать a QVariant
аргумент. Это обязательно возлагает ответственность на подкласс для регистрации их конкретного демонстрационного типа вектора в Q_REGISTER_METATYPE
/qRegisterMetaType
. Едва ли грандиозное предприятие. Клиенты базового класса однако, не будет иметь никакого способа знать что тип QVariant
тип значения, если структура тега также не передается с сигналом. Я рассматриваю это решение, по крайней мере, как замысловатое как то выше, поскольку это вынуждает клиенты абстрактного базового класса API иметь дело с некоторыми gnarlier аспектами системы типов.
Так, есть ли способ достигнуть шаблонного параметра сигнала? Существует ли лучшая архитектура, чем та, которую я предложил?
Существует тип QVariant - вы можете создать на нем свой собственный подтип
и использовать его как параметр (если я поймите свое право и это то, что вы хотите) в сигналах
http://doc.trolltech.com/qq/qq14-metatypes.html#customtypesinqvariant
Одним из упрощений вашего двухуровневого подхода было бы использование класса QObject
в качестве основы без шаблона для шаблона класса, т. Е. что-то вроде
class DataSourceBase : public QObject {
Q_OBJECT
...
signals:
void samplesAcquired(TimeStamp ts, unsigned long nsamples);
};
template<T,U> //sample type and units
class DataSource : public DataSourceBase {
public:
typedef std::vector<boost::units::quantity<U,T> > SampleVector
virtual shared_ptr<SampleVector> acquiredData(TimeStamp ts, unsigned long nsamples);
};
Обратите внимание, что недостатком этого подхода является то, что, поскольку вы не можете использовать макрос Q_OBJECT
в шаблоне класса, информация об этом отсутствует в системе метаобъектов Qt.