From 7b356f0f31e3bbfaeed25dd338c9c9c6d3c3f2c4 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Fri, 20 Dec 2024 16:15:08 +0100 Subject: [PATCH] QtConcurrent: fix support for callables with deduced return type Commit 6ebe3d0f0806069f906522dfe9b81baa3f3478de introduced extra SFINAE checks on the template conditions. However, it broke the case of using callables with deduced return type, because SFINAE does not work for such conditions and treated as a hard error instead. Fix by explicitly providing all template parameters, so that compiler could figure a better overload on its own. Only QtConcurrent::blockingMapped() seems to be affected, but add unit-tests to check all other methods as well. Fixes: QTBUG-130766 Pick-to: 6.8 6.5 Change-Id: I1ddbe712d8ce04ac96ba13841cb569d728cfb943 Reviewed-by: Tatiana Borisova (cherry picked from commit f73765682e7c8f1e0e78b7464deec57c7f2669ba) Reviewed-by: Qt Cherry-pick Bot --- src/concurrent/qtconcurrentmap.h | 6 +- .../tst_qtconcurrentfilter.cpp | 103 ++++++++++++++++++ .../qtconcurrentmap/tst_qtconcurrentmap.cpp | 62 +++++++++++ 3 files changed, 168 insertions(+), 3 deletions(-) diff --git a/src/concurrent/qtconcurrentmap.h b/src/concurrent/qtconcurrentmap.h index bd959f44d3c..b2fd69cdd7b 100644 --- a/src/concurrent/qtconcurrentmap.h +++ b/src/concurrent/qtconcurrentmap.h @@ -433,9 +433,9 @@ ResultType blockingMappedReduced(QThreadPool *pool, | SequentialReduce)) { QFuture future = - mappedReduced(pool, std::forward(sequence), - std::forward(map), - std::forward(reduce), options); + mappedReduced( + pool, std::forward(sequence), std::forward(map), + std::forward(reduce), options); return future.takeResult(); } diff --git a/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp b/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp index e19a596d5de..9744ec4a6a6 100644 --- a/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp +++ b/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp @@ -19,9 +19,11 @@ private slots: void filtered(); void filteredThreadPool(); void filteredWithMoveOnlyCallable(); + void filteredWithGenericCallable(); void filteredReduced(); void filteredReducedThreadPool(); void filteredReducedWithMoveOnlyCallables(); + void filteredReducedWithGenericCallable(); void filteredReducedDifferentType(); void filteredReducedInitialValue(); void filteredReducedInitialValueThreadPool(); @@ -428,6 +430,53 @@ void tst_QtConcurrentFilter::filteredWithMoveOnlyCallable() } } +void tst_QtConcurrentFilter::filteredWithGenericCallable() +{ + const QList intList { 1, 2, 3, 4 }; + const QList intListEven { 2, 4 }; + + auto keepEven = [](auto val) { return (val & 1) == 0; }; + { + const auto result = QtConcurrent::filtered(intList, keepEven).results(); + QCOMPARE(result, intListEven); + } + { + const auto result = QtConcurrent::filtered(intList.begin(), intList.end(), + keepEven).results(); + QCOMPARE(result, intListEven); + } + { + const auto result = QtConcurrent::blockingFiltered(intList, keepEven); + QCOMPARE(result, intListEven); + } + { + const auto result = QtConcurrent::blockingFiltered>(intList.begin(), + intList.end(), + keepEven); + QCOMPARE(result, intListEven); + } + + QThreadPool pool; + { + const auto result = QtConcurrent::filtered(&pool, intList, keepEven).results(); + QCOMPARE(result, intListEven); + } + { + const auto result = QtConcurrent::filtered(&pool, intList.begin(), intList.end(), + keepEven).results(); + QCOMPARE(result, intListEven); + } + { + const auto result = QtConcurrent::blockingFiltered(&pool, intList, keepEven); + QCOMPARE(result, intListEven); + } + { + const auto result = QtConcurrent::blockingFiltered>(&pool, intList.begin(), + intList.end(), keepEven); + QCOMPARE(result, intListEven); + } +} + template intList { 1, 2, 3, 4 }; + const auto sum = 6; + + auto keepEven = [](auto val) { return (val & 1) == 0; }; + auto sumValues = [](auto &sum, auto val) { sum += val; }; + + { + const auto result = QtConcurrent::filteredReduced(intList, keepEven, + sumValues).result(); + QCOMPARE(result, sum); + } + { + const auto result = QtConcurrent::filteredReduced(intList.begin(), intList.end(), + keepEven, sumValues).result(); + QCOMPARE(result, sum); + } + { + const auto result = QtConcurrent::blockingFilteredReduced(intList, keepEven, sumValues); + QCOMPARE(result, sum); + } + { + const auto result = QtConcurrent::blockingFilteredReduced(intList.begin(), + intList.end(), + keepEven, sumValues); + QCOMPARE(result, sum); + } + + QThreadPool pool; + { + const auto result = QtConcurrent::filteredReduced(&pool, intList, keepEven, + sumValues).result(); + QCOMPARE(result, sum); + } + { + const auto result = QtConcurrent::filteredReduced(&pool, intList.begin(), + intList.end(), keepEven, + sumValues).result(); + QCOMPARE(result, sum); + } + { + const auto result = QtConcurrent::blockingFilteredReduced(&pool, intList, + keepEven, sumValues); + QCOMPARE(result, sum); + } + { + const auto result = QtConcurrent::blockingFilteredReduced(&pool, intList.begin(), + intList.end(), keepEven, + sumValues); + QCOMPARE(result, sum); + } +} + void tst_QtConcurrentFilter::filteredReducedDifferentType() { const QList numberList {1, 2, 3, 4}; diff --git a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp index 3e3165013f8..ff2c012996b 100644 --- a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp +++ b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp @@ -22,9 +22,11 @@ private slots: void mapped(); void mappedThreadPool(); void mappedWithMoveOnlyCallable(); + void mappedWithGenericCallable(); void mappedReduced(); void mappedReducedThreadPool(); void mappedReducedWithMoveOnlyCallable(); + void mappedReducedWithGenericCallable(); void mappedReducedDifferentType(); void mappedReducedInitialValue(); void mappedReducedInitialValueThreadPool(); @@ -754,6 +756,32 @@ void tst_QtConcurrentMap::mappedWithMoveOnlyCallable() } } +void tst_QtConcurrentMap::mappedWithGenericCallable() +{ + QList intList{1, 2, 3}; + QList expectedResult{"1", "2", "3"}; + + auto toString = [](const auto &el) { return std::to_string(el); }; + { + const auto res = QtConcurrent::mapped(intList, toString).results(); + QCOMPARE_EQ(res, expectedResult); + } + { + const auto res = QtConcurrent::blockingMapped(intList, toString); + QCOMPARE_EQ(res, expectedResult); + } + + QThreadPool pool; + { + const auto res = QtConcurrent::mapped(&pool, intList, toString).results(); + QCOMPARE_EQ(res, expectedResult); + } + { + const auto res = QtConcurrent::blockingMapped(&pool, intList, toString); + QCOMPARE_EQ(res, expectedResult); + } +} + int intSquare(int x) { return x * x; @@ -1149,6 +1177,40 @@ void tst_QtConcurrentMap::mappedReducedWithMoveOnlyCallable() } } +void tst_QtConcurrentMap::mappedReducedWithGenericCallable() +{ + QList intList{1, 2, 3}; + const std::string expectedResult{"123"}; + + auto toString = [](const auto &el) { return std::to_string(el); }; + auto appendString = [](auto &res, const auto &el) { res.append(el); }; + { + const auto res = QtConcurrent::mappedReduced(intList, toString, appendString, + OrderedReduce).result(); + QCOMPARE_EQ(res, expectedResult); + } + { + const auto res = QtConcurrent::blockingMappedReduced(intList, toString, + appendString, + OrderedReduce); + QCOMPARE_EQ(res, expectedResult); + } + + QThreadPool pool; + { + const auto res = QtConcurrent::mappedReduced(&pool, intList, toString, + appendString, + OrderedReduce).result(); + QCOMPARE_EQ(res, expectedResult); + } + { + const auto res = QtConcurrent::blockingMappedReduced(&pool, intList, toString, + appendString, + OrderedReduce); + QCOMPARE_EQ(res, expectedResult); + } +} + void tst_QtConcurrentMap::mappedReducedDifferentType() { const QList intList {1, 2, 3};