Передать тип возвращаемого значения для шаблонной функции из switch ? ( в вопросе сложночитаемый код)
Вступление:
Есть public метод OpenFile со следующей сигнатурой:
static bool OpenFile(QString filePath,FileType fTtpe,DataContainerType containerT,QIODevice::OpenModeFlag rwFlag=QIODevice::ReadWrite);
Помимо всего прочего, в него передается элемент перечисления DataContainerType, следующего вида:
enum DataContainerType
{
QStringListContainer,
QMapContainer,
ListOfListContaineer
};
Внутри OpenFile - вызывается шаблонный метод readData:
template<typename retT,typename containerCastClass,typename castedClassType, typename obj_class, typename obj, typename ...args>
static retT readData( containerCastClass c,castedClassType c1,obj_class cl, obj o,args... ar);
Подробнее, про написание этого метода, я задавал отдельный вопрос
Пример его вызова:
readData<QStringList>(static_cast<QStringList(QVariant::*)() const>(&QVariant::toStringList),
static_cast<void(QStringList::*)(const QList<QString> &t)>(&QStringList::append),
static_cast< QByteArray ( QIODevice:: * )(qint64 maxSize) >(&QFile::readLine),
currentOpenTxt,
qint64{0});
Собственно, основная работа метода, не учитывая дополнительных проверок:
auto read{
[&]()->auto{
static auto castedContainer = std::invoke(c, currentContainer);// convert QVariant to QStringList, QMap..
qDebug()<<typeid (castedContainer).raw_name();
QString readedData=std::invoke(cl,o,ar...); //read line from txt, row/column from xlsx
std::invoke(c1,castedContainer,retT({readedData}));//append, insert...
return castedContainer;
}
};
Суть вопроса: Как, в зависимости от DataContainerType - задать тип для параметра возвращаемого значения, не дублируя код?
Поясню:
Как, вместо этого:
switch (containerT) {
case DataContainerType::QStringListContainer:
readData<QStringList>(static_cast<QStringList(QVariant::*)() const>(&QVariant::toStringList),
static_cast<void(QStringList::*)(const QList<QString> &t)>(&QStringList::append),
static_cast< QByteArray ( QIODevice:: * )(qint64 maxSize) >(&QFile::readLine),
currentOpenTxt,
qint64{0});
break;
case DataContainerType::QMapContainer:
readData<QMap<QString,QString>>(static_cast<QMap<QString,QString>(QVariant::*)() const>(&QVariant::toMap),
static_cast<QMap::iterator(QMap<QString,QString>::*)(const Key &key, const T &value)>(&QMap<QString,QString>::insert),
static_cast< QByteArray ( QIODevice:: * )(qint64 maxSize) >(&QFile::readLine),
currentOpenTxt,
qint64{0});
break;
case DataContainerType::ListOfListContaineer:
readData<QList<QStringList>>(static_cast<QList<QVariant>(QVariant::*)() const>(&QVariant::toList),
static_cast<void(QList::*)(const QList<QString> &t)>(&QList<QString>::append),
static_cast< QByteArray ( QIODevice:: * )(qint64 maxSize) >(&QFile::readLine),
currentOpenTxt,
qint64{0});
break;
}
Сделать что-то вроде: (псевдокод)
auto _type;
auto _toContainer;
auto containerOperation;
switch (containerT) {
case DataContainerType::QStringListContainer:
_type=&QStringList;
_toContainer=static_cast<QStringList(QVariant::*)() const>(&QVariant::toStringList);
containerOperation=static_cast<void(QStringList::*)(const QList<QString> &t)>(&QStringList::append);
break;
case DataContainerType::QMapContainer:
_type=&QMap<QString,QString>;
_toContainer=static_cast<QMap<QString,QString>(QVariant::*)() const>(&QVariant::toMap);
containerOperation=static_cast<QMap::iterator(QMap<QString,QString>::*)(const Key &key, const T &value)>(&QMap<QString,QString>::insert);
break;
case DataContainerType::ListOfListContaineer:
_type=&QList<QString>
_toContainer=static_cast<QList<QVariant>(QVariant::*)() const>(&QVariant::toList);
containerOperation= static_cast<void(QList::*)(const QList<QString> &t)>(&QList<QString>::append);
break;
}
readData<_type>(_toContainer,
containerOperation,
static_cast< QByteArray ( QIODevice:: * )(qint64 maxSize) >(&QFile::readLine),
currentOpenTxt,
qint64{0});
Зачем все это нужно!?
У меня работа метода по сути зависит от двух параметров - тип читаемого файла и тип принимающего контейнера. Так вот, что бы не проверять каждый из 3-х типов контейнеров, для каждого из 3-х (возможно в будущем - больше) типов файлов (понятно, что выполнится одно ветка, но мы говорим про объемы кода и нецелесообразность его дублирования) - хотелось бы вынести эту проверку до проверки типа файла.
Ответы (1 шт):
Я, конечно, не знаю задачи и проекта вообще, но тут я бы реализовал набор классов: базовый (основной функционал и виртуальный метод чтения данных) и Х наследников, в которых виртуальный метод определён.