Search code examples
c++qtc++11qmap

Iterating over a QMap with for


I've a QMap object and I am trying to write its content to a file.

QMap<QString, QString> extensions;
//.. 

for(auto e : extensions)
{
  fout << e.first << "," << e.second << '\n';
}  

Why do I get: error: 'class QString' has no member named 'first' nor 'second'

Is e not of type QPair?


Solution

  • Qt 6.4 and later

    Use QMap::asKeyValueRange as follows:

    for (auto [key, value] : map.asKeyValueRange()) {
        qDebug() << key << value;
    }
    

    From Qt 5.10 to Qt 6.3

    Use QMap::keyValueBegin and QMap::keyValueEnd as follows:

    for (auto it = map.keyValueBegin(); it != map.keyValueEnd(); ++it) {
        qDebug() << it->first << it->second;
    }
    

    The QMap::asKeyValueRange function can be backported from Qt 6.4 with just a few lines of code, allowing to use key-value ranges in Qt 5.10 to Qt 6.3 as well (C++17 required):

    for (auto [key, value] : asKeyValueRange(map)) {
        qDebug() << key << value;
    }
    

    From Qt 4 to Qt 5.9

    Use QMap::begin and QMap::end as follows:

    for (auto it = map.begin(); it != map.end(); ++it) {
        qDebug() << it.key() << it.value();
    }
    

    The loop can be wrapped into a range with some lines of additional code, allowing to use range-based for loops in Qt 4 to Qt 5.9 as well (C++11 required):

    for (auto it : toRange(map)) {
        qDebug() << it.key() << it.value();
    }
    

    Other options

    (This is the original answer.)

    Use QMap::toStdMap to convert the map into a std::map and then iterate over that. Note that the performance will be poor, since this will copy the entire map.

    for (auto it : map.toStdMap()) {
        qDebug() << it.first << it.second;
    }
    

    Iterate over the QMap::keys and look up each associated QMap::value. Note that the performance will be extremely poor, since this will copy all keys and then separately search for each value.

    for (auto key : map.keys()) {
        qDebug() << key << map.value(key);
    }