суббота, 24 мая 2014 г.

Идеальное число параллельных потоков в Qt.


Максимальное число эффективно работающих (на CPU) параллельных потоков, как правило ровняется числу ядер центрального процессора. Библиотека Qt имеет возможность определять это число, а получить его можно следующим образом:
int threadCount = QThread::idealThreadCount();
Подробнее: QThread

суббота, 22 марта 2014 г.

Qt & C++11

     В предыдущем сниппете использовались конструкции, ставшие доступными начиная с версии стандарта 2011 года - С++11. Для использования возможностей стандарта С++11 в среде Qt, необходимо включить его поддержку в .pro файле проекта:

CONFIG += c++11
Подробнее о C++ в Qt: http://www.ics.com/blog/qt-and-c11#.Uy258Pl_t8E

Custom class as key for QMap and QHash


     В Qt есть замечательные контейнеры для самых различных задач и ситуаций. В том числе ассоциативные массивы QMap и QHash. В качестве ключей для этих контейнеров можно использовать многие стандартные классы Qt, но иногда может возникнуть необходимость в собственной реализации ключа, для этого нужно реализовать несколько методов в собственном классе, а именно - для QMap достаточно определить оператор меньше (bool operator<), а для QHash - оператор равно (bool operator==), а также перегрузить функцию uint qHash() принимающую в качестве параметра объект нашего класса ключа. Далее приведен код класса CustomKey, который можно использовать как ключ для QMap и  QHash, с реализацией всех необходимых методов, а также код демонстрирующий использование данного класса, и в качестве бонуса - различные способы обхода Qt контейнеров, в том числе, способы основанные на возможностях стандарта с++11 (auto, range-based for loops).


customkey.h
#define CUSTOMKEY_H
#include <QHash>

class CustomKey
{
public:
    CustomKey(const int &id = 0);

    int id() const {
        return m_id;
    }

    bool operator< (const CustomKey &other) const {
        return id() < other.id();
    }

    bool operator== (const CustomKey &other) const {
        return id() == other.id();
    }

private:
    int m_id;
};

inline uint qHash(const CustomKey &key, uint seed) {
    return qHash(key.id(), seed);
}

#endif // CUSTOMKEY_H
main.cpp
#include <QCoreApplication>
#include <QMap>
#include <QMapIterator>
#include <QHash>
#include <QHashIterator>
#include <QDebug>

#include "customkey.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QMap<CustomKey, QString> map;
    QHash<CustomKey, QString> hash;

    for (int i = 0; i < 5; ++i) {
        map.insert(CustomKey(i), QString::number(i));
        hash.insert(CustomKey(i), QString::number(i*10));
    }

    /*
     * Index
    */
    qDebug() << "Indexing:\nQMap value";
    for (int i = 0; i < 5; ++i) {
        qDebug() << map[i];
    }

    qDebug() << "QHash value";
    for (int i = 0; i < 5; ++i) {
        qDebug() << hash[CustomKey(i)];
    }

    /*
     * STL style iterators for QMap and QHash
    */
    qDebug() << endl << "STL style:" << endl << "Key, value. QMap";
    for (auto it = map.begin(); it != map.end(); ++it) {
        qDebug() << it.key().id() << it.value();
    }

    qDebug() << "Key, value. QHash";
    for (auto it = hash.begin(); it != hash.end(); ++it) {
        qDebug() << it.key().id() << it.value();
    }

    /*
     * Java style iterators for QMap and QHash
    */
    qDebug() << endl << "Java style:" << endl << "Key, value. QMap";
    QMapIterator<CustomKey, QString> mapIt(map);
    while (mapIt.hasNext()) {
        mapIt.next();
        qDebug() << mapIt.key().id() << mapIt.value();
    }

    qDebug() << "Key, value. QHash";
    QHashIterator<CustomKey, QString> hashIt(hash);
    while (hashIt.hasNext()) {
        hashIt.next();
        qDebug() << hashIt.key().id() << hashIt.value();
    }

    /*
     * The foreach keyword for QMap and QHash
    */
    qDebug() << endl << "The foreach keyword:" << endl << "QMap key";
    foreach (const CustomKey &key, map.keys()) {
        qDebug() << key.id();
    }
    qDebug() << "QMap value";
    foreach (const QString &str, map) {
        qDebug() << str;
    }

    qDebug() << "QHash key";
    foreach (const CustomKey &key, hash.keys()) {
        qDebug() << key.id();
    }
    qDebug() << "QHash value";
    foreach (const QString &str, hash) {
        qDebug() << str;
    }

    /*
     * Range-based for loops
    */
    qDebug() << endl << "Range-based for loops:\nQMap";
    for (auto it : map) {
        qDebug() << it;
    }
    qDebug() << "QHash";
    for (auto it : hash) {
        qDebug() << it;
    }

    return a.exec();
}

P.S.: Не стоит забывать читать документацию Qt. Ссылки по теме:
1. QMap: http://qt-project.org/doc/qt-5.0/qtcore/qmap.html#details
2. QHash: http://qt-project.org/doc/qt-5.0/qtcore/qhash.html#details