Misleading Qt6 upgrade instructions for QMap::unite() deprecation

We are working on updating our application from Qt5 to Qt6 and has found that clazy gave some useful hints.

However, we have come across a misleading recommendation: it recommended to switch from a QMap to using a QMultiMap because we used the unite() method that got removed in Qt6.

QMap::unite() is removed in Qt 6.
For duplicating keys, use QMultiMap.
Migrate by replacing unite() calls with explicit insert() or += into a QMultiMap.

Since QMap cannot contain duplicate keys, developers that have been using QMap don’t need duplicate keys, so they should not be recommended to use QMultiMap. Instead, they should be instructure to switch to an equivalent non-deprecated method:

QMap::unite() is removed in Qt 6.
Migrate by replacing unite() calls with insert() or +=.

In Qt5 QMap could actually contain duplicated keys, see Obsolete Members for QMap | Qt Core 5.15.19.

Thanks for the clarification. Indeed, internally storage of multiple values are possible. However, in most cases developers are not aware of this obscure, unexpected internal behavior.

For example, I searched in the Qt documentation and did not find the page you referred to because both web search and chatbots just took me to regular documentation page (without the obsolete methods).

I tested the behavior of unite and I’ve found that the method overwrote the existing value in that key:

QMap<QString, QString> test1;
test1["a"] = "b";
test1["c"] = "d";
QMap<QString, QString> test2;
test2["c"] = "e";
test2["d"] = "f";

test1.unite(test2);

std::cout << "Test 1: a: " << test1["a"].toStdString() << std::endl;
std::cout << "Test 1: c: " << test1["c"].toStdString() << std::endl;
std::cout << "Test 1: c: " << test1.value("c").toStdString() << std::endl;
std::cout << "Test 1: d: " << test1["d"].toStdString() << std::endl;

Output:

Test 1: a: b
Test 1: c: e
Test 1: c: e
Test 1: d: f

Everything seemed to confirm that QMap is just a simple map. Based on the page you linked, I now see that I can get the old values out of a Qt5 QMap object:

std::cout << "Test 1: c number of values: " << test1.values("c").size() << std::endl;

Output:

Test 1: c number of values: 2

However, most likely only a very small fraction of developers used QMap intentionally as a QMultiMap.


To make your tool more helpful for the majority of developers, I would recommend to modify the message to something like this:

If the QMap is not intended to store multiple values for a key (this is the most common case) then replace unite() by operator+= or insert() method.
If values() method of the QMap is used then the QMap is intended to store multiple values for a key and you need to switch to using QMultiMap in Qt6.

(I am not allowed to post a link, but probably the relevant code is around http://invent.kde.org/sdk/clazy/-/blob/master/src/checks/manuallevel/qt6-deprecated-api-fixes.cpp#L699)

1 Like