2011-03-31 2 views
1

Могу ли я определить QList, чтобы он содержал набор шаблонных структур, причем каждая структура была определена для разных типов?QList пользователя templated defined structs

Рассмотрим:

template<typename T>struct AA 
{ 
    T value; 
} 

Могу ли я объявить 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 для выполнения такой операции?

Thanks,

Vishnu.

+1

Какую проблему вы действительно пытаетесь решить здесь? –

+0

Сериализация JSON в простые в использовании конструкции C++ .. –

ответ

2

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

Эта концепция смешанных типов в одном контейнере не работает так хорошо в строго типизированном мире C++. Объекты Variant являются ближайшими, и даже тогда не для нецелевых типов, не создавая свой собственный класс супервыражений, который вы могли бы сделать путем подкласса 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, чтобы играть хорошо с любыми дополнительными типами, поэтому он чувствует себя более последовательным.

+0

В моем коде я хочу иметь фреймворк, который читает файлы JSON в очень простые и простые в использовании структуры. В JSON нельзя предсказать тип следующей пары имя/значение, которая должна быть прочитана, тем самым генерируя требование для нескольких типов в одном массиве или структуре. –

+0

Итак, вы не хотите определять структуру, которая имеет каждый тип, поскольку это было бы расточительно. Если это всегда пара ключей/значений, возможно, «QMap » будет работать для вас. Если у вас есть несколько значений для одного и того же ключа, вместо этого вы должны использовать 'QMultiMap'. – AJG85

1

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

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

+0

Я не думаю, что могу использовать boost в моем проекте, есть ли такая оболочка в Qt ?? –

+0

'QVariant' будет делать для типов типа' int' или 'double' – Erik

+0

Вы можете использовать boost в QT ... но вам не нужно, поскольку QT имеет довольно много аналогичной функциональности. – AJG85

0

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

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

0

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

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

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

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

+0

Может ли QVariant хранить не-QObject? i.e может ли он хранить экземпляры структуры, подобные тем, которые я использовал выше (например, myIntStruct и myDoubleStruct)? –

+0

[Кажется, это возможно.] (Http://doc.trolltech.com/main-snapshot/qvariant.html#fromValue) Я никогда не использовал это сам, но это выглядит довольно просто. Вам нужно иметь несколько конструкторов по умолчанию для ваших классов, и вам нужно использовать [этот макрос] (http://doc.trolltech.com/main-snapshot/qmetatype.html#Q_DECLARE_METATYPE) ... Но, как я уже сказал, Я не знаком с деталями - удачи! –