У меня есть шаблон, похожий на стратегию, где интерфейс стратегии — IFilter, контекст — класс Context, Filter1, Filter2. .. и т. д. являются конкретными стратегиями, CommonFilter является промежуточным слоем между стратегией и конкретной стратегией для некоторых сервисных операций.
Структура наследования IFilter > CommonFilter > Specific_filters
У меня много классов фильтров, каждый фильтр может работать с различными типами массивов числовых данных (int, int16, uint16, float, double... и т.д.). Фильтры отличаются друг от друга, но внутри одного фильтра они одинаково работают с разными числовыми типами.
Каждый фильтр получает на вход структуру - FilterMetaData, которая имеет: источник данных, тип данных и размер данных. На выходе фильтр выдает такую же структуру. FilterMetaData apply(const FilterMetaData metaData); Фильтр может принимать, например, uint16 и выводит uint16 для другого фильтра в цепочке.
Фильтры имеют базовый класс CommonFilter, который проверяет FilterMetaData. CommonFilter реализует интерфейс IFilter;
У меня есть список фильтров QList m_filters. Я хочу выполнить итерацию по объектам фильтра, подобным этому
class Context {...
for(auto filter : m_filters)
{
filterMetaData = filter->apply(filterMetaData);//parse type of previous filter and work with it
}
И я хочу, чтобы тип данных фильтра выбирался автоматически из поля структуры FilterMetaData::typeOfData; Так что это должна быть цепочка фильтров. Эта цепочка будет вызываться несколько раз;
Поэтому я не знаю, как вызвать фильтр с определенным типом, я не хочу делать условие типа в каждом фильтре.
p.s. я использую старый компилятор gcc 4.4.7, совместимый только с ранним С++ 0x
p.p.s добавлен конкретный пример фильтра. Итак, как я могу автоматически вызывать apply‹ T> в конкретном фильтре на основе числового типа. Если есть Фильтр1, Фильтр2... ФильтрN. Я не хочу проверять тип в каждом фильтре, я хочу сделать это один раз. Должна быть вызвана вся цепочка фильтров, один за другим.
например.
data in/out uint16 array uint16 array uint8 array ...
--------->Filter1--------->Filter2--------->Filter3----->...
class IFilter
{
public:
virtual ~IFilter(){}
// do filtration
virtual FilterMetaData apply(const FilterMetaData metaData) = 0;
};
enum TypeOfData
{
Uint_8,
Uint_16,
Float
...
};
class FilterMetaData
{
public:
void *dataIn;
TypeOfData typeOfData;
int numOfElements;
};
class CommonFilter : public QObject, public IFilter
{
Q_OBJECT
Q_INTERFACES(IFilter)
public:
explicit CommonFilter(QObject *parent = nullptr);
public:
virtual FilterMetaData apply(const FilterMetaData metaData) override = 0;
const FilterMetaData metaData() const;
protected:
bool applyMetaData(const FilterMetaData metaData);
private:
FilterMetaData m_metaData;
};
Пример фильтра
class Filter1 : public CommonFilter
{
Q_OBJECT
public:
explicit Filter1(QObject *parent = nullptr);
//common type
FilterMetaData apply(const FilterMetaData metaData) override;
//filtration for specific type
template<typename T>
FilterMetaData apply(const FilterMetaData metaData);
};