получение неизвестного шаблонного объекта из QVariant - PullRequest
0 голосов
/ 04 декабря 2018

У меня есть шаблонный шаблон для хранения ответов из собственного сетевого класса

enum class TaskType {readReg, writeReg, readRnd, writeRnd, readBlock, writeBlock, pause};

template<typename... Args> class Reply {
public:
    Reply(TaskType t, Args...params): t(t), tuple(std::make_tuple(params...)) {}
    Reply();
    TaskType t;
    auto getData() const {return std::get<4>(tuple);}   //simplified getter of safe function that deals with oversizing
private:
    std::tuple<Args ...> tuple;
};

Я регистрирую подписи шаблонов, чтобы хранить их в Qvariant

using ReadRegReply = Reply<TaskType, uint, uint, uint, uint, uint> ;
using WriteReply = Reply<TaskType, uint, uint, uint> ;
using ReadRndReply = Reply<TaskType, uint, uint, uint, QVector<uint>, QVector<uint>> ;
using ReadBlockReply = Reply<TaskType, uint, uint, uint, uint, QVector<uint>> ;

Q_DECLARE_METATYPE(QVector<uint>)
Q_DECLARE_METATYPE(ReadRegReply)
Q_DECLARE_METATYPE(WriteReply)
Q_DECLARE_METATYPE(ReadRndReply)
Q_DECLARE_METATYPE(ReadBlockReply)

Затем я работаю с ним вот так:

class Task: public QObject{ 
public:
//c-tor and some functions, virtual functions etc
template <class TReply> bool applyReply(TReply reply){
    varReply = QVariant::fromValue(reply);
}
auto getData(){  //here I should return data from tuple inside reply.
   QVariant::Type t = varReply.type();
   auto l = varReply.value<t>();// t is not a constexp // t is not a reply type but enum QVariant::type, as I understand.
   return l.getData(); // l has no method getData
}
QVariant varReply;      //this is the qvariant that contains templated reply;
}

В QVariant я что-то упускаю.Я думал, что зарегистрированный тип должен храниться как-то в Qvariant, но это не так.Другие проблемы: я не могу использовать c ++ 17;он будет использоваться во многих проектах с разными сигнатурами ответов.Есть ли способ сохранить эти типы и добавить их в будущем без полного рефакторинга?Я думал о каком-то классе менеджера, но я мог бы подумать

1 Ответ

0 голосов
/ 04 декабря 2018

QVariant содержит только полезную информацию о типах для встроенных типов, используемых в Qt.Если у вас есть другие типы, вам нужно записать их в другом месте

class Task: public QObject{ 
public:
    template <class TReply> bool applyReply(TReply reply){
        varReply = QVariant::fromValue(reply);
    }
    template <class TReply> TReply getData(){reply.   
       return varReply.value<TReply>();
    }
    QVariant varReply;
}

void usesWriteTask() {
    Task task;
    task.applyReply(WriteReply());
    // ...
    WriteReply back = tast.getData<WriteReply>();
}

В качестве альтернативы, если у вас есть доступ к бусту, вы можете использовать boost::variant, что вдохновило std::variant

class Task: public QObject{ 
public:
     using VarReply = boost::variant<ReadRegReply, WriteReply, ReadRndReply, ReadBlockReply>;
     bool applyReply(VarReply reply) {
         varReply = reply;
     }
     template <class Result> Result getData(boost::static_visitor<Result> & visitor) {
        return varReply.apply_visitor(visitor);
     }
     VarReply varReply;
}
...