Open Source & Linux Lab

It's better when it's simple

User Tools

Site Tools


etc:blog:q_multi_hash_map_qsharedpointer

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
etc:blog:q_multi_hash_map_qsharedpointer [2011/01/27 20:41] voodetc:blog:q_multi_hash_map_qsharedpointer [2011/01/27 21:14] vood
Line 5: Line 5:
 ==== Введение ==== ==== Введение ====
 Библиотека Qt предоставляет множество удобных средств для разработки приложений, например api для взаимодействия с мобильными платформами или набор классов для GUI программ. В данной статье речь пойдет об одной не совсем очевидной особенности совместного использования таких классов как QMultiMap и QSharedPointer. В качестве среды используется Ubuntu 10.04 с установленным Qt 4.6 . Библиотека Qt предоставляет множество удобных средств для разработки приложений, например api для взаимодействия с мобильными платформами или набор классов для GUI программ. В данной статье речь пойдет об одной не совсем очевидной особенности совместного использования таких классов как QMultiMap и QSharedPointer. В качестве среды используется Ubuntu 10.04 с установленным Qt 4.6 .
 +
  
  
Line 14: Line 15:
 ==== Проблема ==== ==== Проблема ====
  
-Впервые с данной проблемой я столкнулся, когда попробовал скомпилировать код, написанный для Qt 4.7, с использованием Qt 4.6. Часть незначительных ошибок удалось решить, исключив использование функций, появившихся в новой версии Qt. Однако несмотря на это, компиляция не была успешной. Дальнейшие изыскания позволили выяснитьчто проблема заключалась в методе  +Впервые с данной проблемой я столкнулся, когда попробовал скомпилировать код, написанный для Qt 4.7, с использованием Qt 4.6. Часть незначительных ошибок удалось решить, исключив использование функций, появившихся в новой версии Qt. Однако одна ошибка казалась очень загадочной.  
-<code text+<code bash
-uniqueKeys()+ In file included from /usr/include/qt4/QtCore/qsharedpointer.h:52, 
 + from /usr/include/qt4/QtCore/QSharedPointer:1, 
 + /usr/include/qt4/QtCore/qsharedpointer_impl.h: In constructor 'QtSharedPointer::ExternalRefCount<T>::ExternalRefCount(const QtSharedPointer::ExternalRefCount<X>&) [with X = Channel, T = DataMark]': 
 + /usr/include/qt4/QtCore/qsharedpointer_impl.h:461: instantiated from 'QSharedPointer<T>::QSharedPointer(const QSharedPointer<X>&) [with X = Channel, T = DataMark]' 
 + /usr/include/qt4/QtCore/qmap.h:782: instantiated from 'QList<T> QMap<Key, T>::uniqueKeys() const [with Key = QSharedPointer<Channel>, T = QSharedPointer<DataMark>]' 
 + src/RSSFeedJSON.cpp:129: instantiated from here 
 + /usr/include/qt4/QtCore/qsharedpointer_impl.h:378: error: no matching function for call to 'QtSharedPointer::Basic<DataMark>::Basic(Channel* const&)' 
 + /usr/include/qt4/QtCore/qsharedpointer_impl.h:150: note: candidates are: QtSharedPointer::Basic<T>::Basic(Qt::Initialization) [with T = DataMark] 
 + /usr/include/qt4/QtCore/qsharedpointer_impl.h:149: note: QtSharedPointer::Basic<T>::Basic(T*) [with T = DataMark] 
 + /usr/include/qt4/QtCore/qsharedpointer_impl.h:123: note: QtSharedPointer::Basic<DataMark>::Basic(const QtSharedPointer::Basic<DataMark>&)
 </code>   </code>  
-класса QMultiMap, у которого в качестве типа для ключевых значений был использован тип  QSharedPointer<...>.+Больше всех настораживало сообщение  
 +<code bash> 
 + /usr/include/qt4/QtCore/qmap.h:782: instantiated from 'QList<T> QMap<Key, T>::uniqueKeys() const [with Key = QSharedPointer<Channel>, T = QSharedPointer<DataMark>]' 
 +</code> 
 +так как сигнатура функиции uniqueKeys должна выглядеть иначе.
  
-Рассмотрим небольшой пример, который наглядно демонстрирует специфику совместного использования QMultiMap и QSharedPointer в Qt 4.6.+Дальнейшие изыскания позволили выяснить, что проблема заключалась в использовании QMultiMapу которого в качестве типа для ключевых значений был использован тип  QSharedPointer<...>.
  
-<code text>+Рассмотрим небольшой пример, который наглядно демонстрирует специфику совместного использования QMultiMap и QSharedPointer в Qt 4.6. 
 +<code c++>
 #include <QSharedPointer> #include <QSharedPointer>
 #include <QMultiMap> #include <QMultiMap>
Line 44: Line 59:
 Если мы попытаемся скомпилировать данный пример, то получим следующие ошибки: Если мы попытаемся скомпилировать данный пример, то получим следующие ошибки:
  
-<code text>+<code bash>
 In file included from /usr/include/qt4/QtCore/QMultiMap:1, In file included from /usr/include/qt4/QtCore/QMultiMap:1,
                  from main.cpp:2:                  from main.cpp:2:
-/usr/include/qt4/QtCore/qmap.h: In member function QList<T> QMap<Key, T>::uniqueKeys() const [with Key = QSharedPointer<int>, T = QString]:+/usr/include/qt4/QtCore/qmap.h: In member function 'QList<T> QMap<Key, T>::uniqueKeys() const [with Key = QSharedPointer<int>, T = QString]':
 main.cpp:23:   instantiated from here main.cpp:23:   instantiated from here
-/usr/include/qt4/QtCore/qmap.h:782: error: no match for operator<’ in aKey < i.QMap<Key, T>::const_iterator::key [with Key = QSharedPointer<int>, T = QString]()+/usr/include/qt4/QtCore/qmap.h:782: error: no match for 'operator<in 'aKey < i.QMap<Key, T>::const_iterator::key [with Key = QSharedPointer<int>, T = QString]()'
 /usr/include/qt4/QtCore/qchar.h:385: note: candidates are: bool operator<(QChar, QChar) /usr/include/qt4/QtCore/qchar.h:385: note: candidates are: bool operator<(QChar, QChar)
 /usr/include/qt4/QtCore/qbytearray.h:520: note:                 bool operator<(const QByteArray&, const QByteArray&) /usr/include/qt4/QtCore/qbytearray.h:520: note:                 bool operator<(const QByteArray&, const QByteArray&)
Line 58: Line 73:
 /usr/include/qt4/QtCore/qstring.h:953: note:                 bool operator<(const QLatin1String&, const QLatin1String&) /usr/include/qt4/QtCore/qstring.h:953: note:                 bool operator<(const QLatin1String&, const QLatin1String&)
 /usr/include/qt4/QtCore/qstring.h:1181: note:                 bool operator<(const QStringRef&, const QStringRef&) /usr/include/qt4/QtCore/qstring.h:1181: note:                 bool operator<(const QStringRef&, const QStringRef&)
-/usr/include/qt4/QtCore/qmap.h: In function bool qMapLessThanKey(const Key&, const Key&) [with Key = QSharedPointer<int>]+/usr/include/qt4/QtCore/qmap.h: In function 'bool qMapLessThanKey(const Key&, const Key&) [with Key = QSharedPointer<int>]'
-/usr/include/qt4/QtCore/qmap.h:760:   instantiated from QMapData::Node* QMap<Key, T>::mutableFindNode(QMapData::Node**, const Key&) const [with Key = QSharedPointer<int>, T = QString] +/usr/include/qt4/QtCore/qmap.h:760:   instantiated from 'QMapData::Node* QMap<Key, T>::mutableFindNode(QMapData::Node**, const Key&) const [with Key = QSharedPointer<int>, T = QString]' 
-/usr/include/qt4/QtCore/qmap.h:576:   instantiated from QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key&, const T&) [with Key = QSharedPointer<int>, T = QString] +/usr/include/qt4/QtCore/qmap.h:576:   instantiated from 'QMap<Key, T>::iterator QMap<Key, T>::insertMulti(const Key&, const T&) [with Key = QSharedPointer<int>, T = QString]' 
-/usr/include/qt4/QtCore/qmap.h:953:   instantiated from typename QMap<Key, T>::iterator QMultiMap<Key, T>::insert(const Key&, const T&) [with Key = QSharedPointer<int>, T = QString]+/usr/include/qt4/QtCore/qmap.h:953:   instantiated from 'typename QMap<Key, T>::iterator QMultiMap<Key, T>::insert(const Key&, const T&) [with Key = QSharedPointer<int>, T = QString]'
 main.cpp:20:   instantiated from here main.cpp:20:   instantiated from here
-/usr/include/qt4/QtCore/qmap.h:107: error: no match for operator<’ in key1 < key2+/usr/include/qt4/QtCore/qmap.h:107: error: no match for 'operator<in 'key1 < key2'
 /usr/include/qt4/QtCore/qchar.h:385: note: candidates are: bool operator<(QChar, QChar) /usr/include/qt4/QtCore/qchar.h:385: note: candidates are: bool operator<(QChar, QChar)
 /usr/include/qt4/QtCore/qbytearray.h:520: note:                 bool operator<(const QByteArray&, const QByteArray&) /usr/include/qt4/QtCore/qbytearray.h:520: note:                 bool operator<(const QByteArray&, const QByteArray&)
Line 81: Line 96:
 из-за которой и происходит сбой компиляции. Вот так выглядит ее прототип в документации Qt [[http://doc.qt.nokia.com/4.6/qmap.html#uniqueKeys|uniqueKeys]] : из-за которой и происходит сбой компиляции. Вот так выглядит ее прототип в документации Qt [[http://doc.qt.nokia.com/4.6/qmap.html#uniqueKeys|uniqueKeys]] :
 <code text>QList<Key> QMap::uniqueKeys () const</code> <code text>QList<Key> QMap::uniqueKeys () const</code>
-Очевидно, что возвращаемые значения в обоих случаях не совпадают.+Очевидно, что возвращаемые значения в обоих случаях не совпадают и нам удалось повторить ошибку на более простом примере\\
 Обратимся к описанию данной функции. Исходя из документации она возвращает список всех ключей в QMultiMap в порядке возрастания. Логично предположить, что основная проблема заключается в сортировке полученного списка ключей, ввиду отсутствия оператора сравнения определенного для типа QSharedPointer<T> Обратимся к описанию данной функции. Исходя из документации она возвращает список всех ключей в QMultiMap в порядке возрастания. Логично предположить, что основная проблема заключается в сортировке полученного списка ключей, ввиду отсутствия оператора сравнения определенного для типа QSharedPointer<T>
 Определим свой оператор сравнения следующим образом: Определим свой оператор сравнения следующим образом:
-<code text>+<code c++>
 template <class T> template <class T>
 bool operator <(const  QSharedPointer<T>& a, const  QSharedPointer<T>& b){ bool operator <(const  QSharedPointer<T>& a, const  QSharedPointer<T>& b){
Line 93: Line 108:
  
 Проблема, похожая на описанную выше, возникает при замене QMultiMap на QMultiHash в примере. Для нормальной компиляции в таком случае необходимо определить собственную функцию qHash со следующим прототипом: Проблема, похожая на описанную выше, возникает при замене QMultiMap на QMultiHash в примере. Для нормальной компиляции в таком случае необходимо определить собственную функцию qHash со следующим прототипом:
-<code text>+<code c++>
 template <class T> template <class T>
 uint qHash(const QSharedPointer<T>& a); uint qHash(const QSharedPointer<T>& a);
Line 100: Line 115:
  
 ==== Заключение ==== ==== Заключение ====
 +Очевидно, что перегрузка оператора "<" для типа QSharedPointer<T> также следует и из сообщений компилятора. А это показывает, что написание простого примера ошибки в большом приложении позволяет весьма тривиальным образом найти ее причины.
 Описанная проблема устранена в новой версии Qt 4.7, которая входит в состав Qt SDK 1.1. Однако предложенное здесь решение остается актуальным, так как на момент написания статьи в OVI находится  Qt 4.6. Описанная проблема устранена в новой версии Qt 4.7, которая входит в состав Qt SDK 1.1. Однако предложенное здесь решение остается актуальным, так как на момент написания статьи в OVI находится  Qt 4.6.
  
etc/blog/q_multi_hash_map_qsharedpointer.txt · Last modified: 2011/01/27 21:30 by kkv