QList пользовательских шаблонных определенных структур - PullRequest
1 голос
/ 31 марта 2011

Могу ли я определить QList так, чтобы он содержал коллекцию шаблонных структур, причем каждая структура определена в своем типе ??что он держит разные экземпляры АА ??что-то вроде:

struct<int> myIntStruct;
myIntStruct.value = 10;
struct<double> myDobleStruct;
myDoubleStruct = 12.2;

template<typename T>
QList<struct AA<T>> myList;
myList.push_back(myIntStruct);
myList.push_back(myDoubleStruct);

Мое мнение таково, что QList должен содержать сущности одного и того же типа данных (даже для шаблонных объектов), и поэтому вышеуказанная операция недопустима.В таком случае, какую структуру я могу использовать в Qt для выполнения подобной операции ??

Спасибо,

Вишну.

Ответы [ 4 ]

2 голосов
/ 01 апреля 2011

Почему вы хотите, чтобы в контейнере были разнородные объекты, это, вероятно, недостаток дизайна.Однако некоторые языки поддерживают это, например Smalltalk, который имеет концепцию Bag Collection, которая может содержать смесь различных типов объектов.У Qt уже может быть какой-то класс контейнера-мешка, но я не знаю о его существовании.

Эта концепция смешанных типов в одном контейнере не очень хорошо работает в строго типизированном мире C ++.Вариантные объекты - это самая близкая вещь, и даже не для нецелых типов без создания собственного «супервариантного» класса, который вы можете сделать, создав подкласс QVariant, а затем добавив несколько битов для обработки своих структур.вопрос зачем вам этот функционал?Более простое решение, реализованное в другом месте, вероятно, уменьшит потребность в таком контейнере.

Редактировать: пример Quickie из QMap<QString, QVariant>, чтобы помочь определить, будет ли это работать.

class SomeObject
{
public:
    SomeObject() // default
        : someInt(0), someDouble(0) {}
    SomeObject(int i, double d) // explicit
        : someInt(i), someDouble(d) {}

    int GetSomeInt() const { return someInt; }
    double GetSomeDouble() const { return someDouble; }

private:
    int someInt;
    double someDouble;
};

// must be outside of namespace
Q_DECLARE_METATYPE(SomeObject)

// then you can do stuff like this:
    QMap<QString, QVariant> mapNameToValue;

    // populate map
    mapNameToValue["UserName"] = "User";
    mapNameToValue["Port"] = 10101;
    mapNameToValue["PI"] = 3.14159265;
    mapNameToValue["DateTime"] = QDateTime::currentDateTime();
    QVariant userValue;
    userValue.setValue(SomeObject(5, 34.7));
    mapNameToValue["SomeObject"] = userValue;

    // read from map
    QString userName = mapNameToValue["UserName"].toString();
    unsigned int port = mapNameToValue["Port"].toUInt();
    double PI = mapNameToValue["PI"].toDouble();
    QDateTime date = mapNameToValue["DateTime"].toDateTime();
    SomeObject myObj = mapNameToValue["SomeObject"].value<SomeObject>();

    int someInt = myObj.GetSomeInt();
    double someDouble = myObj.GetSomeDouble();

QVariant ручкиу многих типов есть также шаблоны setValue и value<> для пользовательских типов.Как кратко показано выше, вы должны использовать макрос Q_DECLARE_METATYPE, чтобы зарегистрировать его в QMetaType и предоставить конструктор по умолчанию в случае сбоя преобразования value<>.Он не будет поддерживать некоторые операторы сравнения, поэтому я бы сделал свою собственную версию QVariant и QMetaType, чтобы она хорошо играла с любыми необходимыми дополнительными типами, чтобы она выглядела более согласованной.

1 голос
/ 31 марта 2011

Шаблонный класс - это не класс, это шаблон . Вы можете использовать его для создания экземпляров совершенно не связанных классов , таких как AA<int> и AA<double>.

Чтобы получить нужную вам функциональность - добавление несвязанных классов в контейнер - вам нужен либо контейнер, который специально поддерживает добавление таких несвязанных экземпляров, либо вам нужно обернуть свои объекты, например, в. boost::variant

0 голосов
/ 01 апреля 2011

Я считаю, что MyTemplateClass<int> и MyTemplateClass<double> считаются отдельными типами данных, поэтому вы не можете иметь QList, содержащий оба типа одновременно.

У вас есть опции.Если вы просто храните простые типы данных, проверьте QVariant .Это один тип класса, но он использует объединения для хранения различных типов данных внутри него.И он встроенный, так как вы уже используете Qt!

Если вы пытаетесь хранить более сложные вещи, полиморфные классы, вероятно, помогут вам.Тогда у вас может быть QList MyBaseType* s, и все функции, которые вам нужно вызвать из списка, будут virtual.Вы даже можете сделать MyBaseType наследованным от QVariant, поэтому о хранении данных позаботятся за вас.

Надеюсь, это поможет!

0 голосов
/ 31 марта 2011

Вы правы, что вы не можете иметь неоднородные типы в одном контейнере.

Вы можете обойти это с помощью контейнеров (умных) указателей, boost::any, boost::variant и, я уверен, других механизмов.

...