From 6891e10f9717a51b72583bf18e5a1a8d5f5fd527 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Sun, 9 Jan 2022 10:07:34 +0100 Subject: [PATCH] QFlatMap: add insert_or_assign This does exactly what insert() on Qt associative containers does, but allows to express the intent of using the STL-incompatible Qt insert() semantics, in an STL-compatible way, instead of leaving the reader of the code wondering what semantics are expected. This is part of a very-long-term goal of fixing Qt associative container's insert() behavior, in which QFlatMap, being an affected, but private-API type, is used for proof-of-concept purposes. Task-number: QTBUG-99651 Pick-to: 6.3 6.2 Change-Id: I69010285438259918aef659d3235180c1b5be696 Reviewed-by: Joerg Bornemann --- src/corelib/tools/qflatmap_p.h | 18 +++++ src/plugins/platforms/cocoa/qnsview_tablet.mm | 2 +- .../corelib/tools/qflatmap/tst_qflatmap.cpp | 66 ++++++++++++++++++- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qflatmap_p.h b/src/corelib/tools/qflatmap_p.h index 3b847fc63ac..fd08676ae33 100644 --- a/src/corelib/tools/qflatmap_p.h +++ b/src/corelib/tools/qflatmap_p.h @@ -750,6 +750,24 @@ public: } } + template + std::pair insert_or_assign(const Key &key, M &&obj) + { + auto r = try_emplace(key, std::forward(obj)); + if (!r.second) + *toValuesIterator(r.first) = std::forward(obj); + return r; + } + + template + std::pair insert_or_assign(Key &&key, M &&obj) + { + auto r = try_emplace(std::move(key), std::forward(obj)); + if (!r.second) + *toValuesIterator(r.first) = std::forward(obj); + return r; + } + template = nullptr> void insert(InputIt first, InputIt last) { diff --git a/src/plugins/platforms/cocoa/qnsview_tablet.mm b/src/plugins/platforms/cocoa/qnsview_tablet.mm index 318a32f7cf2..81d90a6fbe1 100644 --- a/src/plugins/platforms/cocoa/qnsview_tablet.mm +++ b/src/plugins/platforms/cocoa/qnsview_tablet.mm @@ -224,7 +224,7 @@ static const QPointingDevice *tabletToolInstance(NSEvent *theEvent) QWindowSystemInterface::handleTabletEnterLeaveProximityEvent(nullptr, timestamp, device, theEvent.isEnteringProximity); // The windowSystemId starts at 0, but is "unique" while in proximity if (theEvent.isEnteringProximity) - devicesInProximity->insert(windowSystemId, device); + devicesInProximity->insert_or_assign(windowSystemId, device); else devicesInProximity->remove(windowSystemId); } diff --git a/tests/auto/corelib/tools/qflatmap/tst_qflatmap.cpp b/tests/auto/corelib/tools/qflatmap/tst_qflatmap.cpp index 1ba060cc918..1de1c3ad71a 100644 --- a/tests/auto/corelib/tools/qflatmap/tst_qflatmap.cpp +++ b/tests/auto/corelib/tools/qflatmap/tst_qflatmap.cpp @@ -53,7 +53,7 @@ private slots: void iterators(); void statefulComparator(); void transparency(); - void try_emplace(); + void try_emplace_and_insert_or_assign(); void viewIterators(); void varLengthArray(); }; @@ -428,7 +428,7 @@ void tst_QFlatMap::transparency() QCOMPARE(m.lower_bound(sv3).value(), "dree"); } -void tst_QFlatMap::try_emplace() +void tst_QFlatMap::try_emplace_and_insert_or_assign() { using Map = QFlatMap; @@ -457,12 +457,32 @@ void tst_QFlatMap::try_emplace() Map m; QVERIFY(m.try_emplace(lvalue(foo), lvalue(qqq)).second); CHECKS(); + QVERIFY(!m.insert_or_assign(lvalue(foo), lvalue(foo)).second); + QCOMPARE(m.value(foo), foo); + } + + { + Map m; + QVERIFY(m.insert_or_assign(lvalue(foo), lvalue(qqq)).second); + CHECKS(); + QVERIFY(!m.try_emplace(lvalue(foo), lvalue(foo)).second); + QCOMPARE(m.value(foo), qqq); } { Map m; QVERIFY(m.try_emplace(lvalue(foo), rvalue(qqq)).second); CHECKS(); + QVERIFY(!m.insert_or_assign(lvalue(foo), rvalue(foo)).second); + QCOMPARE(m.value(foo), foo); + } + + { + Map m; + QVERIFY(m.insert_or_assign(lvalue(foo), rvalue(qqq)).second); + CHECKS(); + QVERIFY(!m.try_emplace(lvalue(foo), rvalue(foo)).second); + QCOMPARE(m.value(foo), qqq); } { @@ -477,18 +497,49 @@ void tst_QFlatMap::try_emplace() QVERIFY(m.try_emplace(lvalue(foo), sb(qqq)).second); QCOMPARE(m.value(foo), qqq); CHECKS(); + QVERIFY(!m.insert_or_assign(lvalue(foo), sb(foo)).second); + QCOMPARE(m.value(foo), foo); + } + + { + Map m; + QVERIFY(m.insert_or_assign(lvalue(foo), sb(qqq)).second); + QCOMPARE(m.value(foo), qqq); + CHECKS(); + QVERIFY(!m.try_emplace(lvalue(foo), sb(foo)).second); + QCOMPARE(m.value(foo), qqq); } { Map m; QVERIFY(m.try_emplace(rvalue(foo), lvalue(qqq)).second); CHECKS(); + QVERIFY(!m.insert_or_assign(rvalue(foo), lvalue(foo)).second); + QCOMPARE(m.value(foo), foo); + } + + { + Map m; + QVERIFY(m.insert_or_assign(rvalue(foo), lvalue(qqq)).second); + CHECKS(); + QVERIFY(!m.try_emplace(rvalue(foo), lvalue(foo)).second); + QCOMPARE(m.value(foo), qqq); } { Map m; QVERIFY(m.try_emplace(rvalue(foo), rvalue(qqq)).second); CHECKS(); + QVERIFY(!m.insert_or_assign(rvalue(foo), rvalue(foo)).second); + QCOMPARE(m.value(foo), foo); + } + + { + Map m; + QVERIFY(m.insert_or_assign(rvalue(foo), rvalue(qqq)).second); + CHECKS(); + QVERIFY(!m.try_emplace(rvalue(foo), rvalue(foo)).second); + QCOMPARE(m.value(foo), qqq); } { @@ -503,6 +554,17 @@ void tst_QFlatMap::try_emplace() QVERIFY(m.try_emplace(rvalue(foo), sb(qqq)).second); QCOMPARE(m.value(foo), qqq); CHECKS(); + QVERIFY(!m.insert_or_assign(rvalue(foo), sb(foo)).second); + QCOMPARE(m.value(foo), foo); + } + + { + Map m; + QVERIFY(m.insert_or_assign(rvalue(foo), sb(qqq)).second); + QCOMPARE(m.value(foo), qqq); + CHECKS(); + QVERIFY(!m.try_emplace(rvalue(foo), sb(foo)).second); + QCOMPARE(m.value(foo), qqq); } #undef CHECKS #undef lvalue