Fix QtConcurrent::blockingMapped to work with non-template sequences

The code for deducing the type of output sequence was assuming that the
input sequence is always a template class and was trying to use the
corresponding container type for the output sequence. Fixed the
deduction code, to assume that the output sequence has the same type as
the input sequence, when it's not a template class. Also added tests to
verify that all QtConcurrent functions support non-template input
sequences.

Fixes: QTBUG-30617
Pick-to: 6.2 6.1
Change-Id: I486fe99f3207cfff5dcceb3712cc7de863067edb
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Sona Kurazyan 2021-09-06 14:37:32 +02:00
parent 2b0e55a3e2
commit 28e194d3b2
4 changed files with 202 additions and 1 deletions

View File

@ -190,7 +190,13 @@ struct ReduceResultTypeHelper<Callable,
// -- MapSequenceResultType // -- MapSequenceResultType
template <class InputSequence, class MapFunctor> template <class InputSequence, class MapFunctor>
struct MapSequenceResultType; struct MapSequenceResultType
{
static_assert(std::is_same_v<typename InputSequence::value_type,
QtPrivate::MapResultType<InputSequence, MapFunctor>>,
"Couldn't deduce the output sequence type, you must specify it explicitly.");
typedef InputSequence ResultType;
};
#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS #ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS

View File

@ -102,6 +102,19 @@ void tst_QtConcurrentFilter::filter()
CHECK_FAIL("member"); CHECK_FAIL("member");
testFilter(intList, intListEven, lambdaIsEven); testFilter(intList, intListEven, lambdaIsEven);
CHECK_FAIL("lambda"); CHECK_FAIL("lambda");
// non-template sequences
{
NonTemplateSequence list({ 1, 2, 3, 4 });
QtConcurrent::filter(list, keepEvenNumbers).waitForFinished();
QCOMPARE(list, NonTemplateSequence({ 2, 4 }));
}
{
NonTemplateSequence list({ 1, 2, 3, 4 });
QtConcurrent::blockingFilter(list, keepEvenNumbers);
QCOMPARE(list, NonTemplateSequence({ 2, 4 }));
}
} }
static QSemaphore semaphore(1); static QSemaphore semaphore(1);
@ -179,6 +192,19 @@ void tst_QtConcurrentFilter::filterThreadPool()
CHECK_FAIL("function"); CHECK_FAIL("function");
testFilterThreadPool(&pool, intList, intListEven, lambdaIsOdd); testFilterThreadPool(&pool, intList, intListEven, lambdaIsOdd);
CHECK_FAIL("lambda"); CHECK_FAIL("lambda");
// non-template sequences
{
NonTemplateSequence list({ 1, 2, 3, 4 });
QtConcurrent::filter(list, keepEvenIntegers).waitForFinished();
QCOMPARE(list, NonTemplateSequence({ 2, 4 }));
}
{
NonTemplateSequence list({ 1, 2, 3, 4 });
QtConcurrent::blockingFilter(list, keepEvenIntegers);
QCOMPARE(list, NonTemplateSequence({ 2, 4 }));
}
} }
void tst_QtConcurrentFilter::filterWithMoveOnlyCallable() void tst_QtConcurrentFilter::filterWithMoveOnlyCallable()
@ -254,6 +280,18 @@ void tst_QtConcurrentFilter::filtered()
testFiltered(intList, intListEven, lambdaIsEven); testFiltered(intList, intListEven, lambdaIsEven);
CHECK_FAIL("lambda"); CHECK_FAIL("lambda");
// non-template sequences
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto future = QtConcurrent::filtered(list, keepEvenIntegers);
QCOMPARE(future.results(), QList({ 2, 4 }));
}
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto result = QtConcurrent::blockingFiltered(list, keepEvenIntegers);
QCOMPARE(result, NonTemplateSequence({ 2, 4 }));
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::filtered(std::vector { 1, 2, 3, 4 }, keepEvenIntegers); auto future = QtConcurrent::filtered(std::vector { 1, 2, 3, 4 }, keepEvenIntegers);
@ -329,6 +367,18 @@ void tst_QtConcurrentFilter::filteredThreadPool()
testFilteredThreadPool(&pool, intList, intListEven, lambdaIsOdd); testFilteredThreadPool(&pool, intList, intListEven, lambdaIsOdd);
CHECK_FAIL("lambda"); CHECK_FAIL("lambda");
// non-template sequences
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto future = QtConcurrent::filtered(&pool, list, keepEvenIntegers);
QCOMPARE(future.results(), QList({ 2, 4 }));
}
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto result = QtConcurrent::blockingFiltered(&pool, list, keepEvenIntegers);
QCOMPARE(result, NonTemplateSequence({ 2, 4 }));
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::filtered(&pool, std::vector { 1, 2, 3, 4 }, keepEvenIntegers); auto future = QtConcurrent::filtered(&pool, std::vector { 1, 2, 3, 4 }, keepEvenIntegers);
@ -561,6 +611,18 @@ void tst_QtConcurrentFilter::filteredReduced()
testFilteredReduced(intList, intSum, lambdaIsEven, lambdaIntSumReduce); testFilteredReduced(intList, intSum, lambdaIsEven, lambdaIntSumReduce);
CHECK_FAIL("lambda-lambda"); CHECK_FAIL("lambda-lambda");
// non-template sequences
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto future = QtConcurrent::filteredReduced(list, keepEvenIntegers, intSumReduce);
QCOMPARE(future.result(), intSum);
}
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto result = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, intSumReduce);
QCOMPARE(result, intSum);
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::filteredReduced(std::vector { 1, 2, 3, 4 }, keepEvenIntegers, auto future = QtConcurrent::filteredReduced(std::vector { 1, 2, 3, 4 }, keepEvenIntegers,
@ -689,6 +751,19 @@ void tst_QtConcurrentFilter::filteredReducedThreadPool()
testFilteredReducedThreadPool(&pool, intList, intSum, lambdaIsOdd, lambdaSumReduce); testFilteredReducedThreadPool(&pool, intList, intSum, lambdaIsOdd, lambdaSumReduce);
CHECK_FAIL("lambda-lambda"); CHECK_FAIL("lambda-lambda");
// non-template sequences
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto future = QtConcurrent::filteredReduced(&pool, list, keepOddIntegers, intSumReduce);
QCOMPARE(future.result(), intSum);
}
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto result =
QtConcurrent::blockingFilteredReduced(&pool, list, keepOddIntegers, intSumReduce);
QCOMPARE(result, intSum);
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::filteredReduced(&pool, std::vector { 1, 2, 3, 4 }, auto future = QtConcurrent::filteredReduced(&pool, std::vector { 1, 2, 3, 4 },
@ -987,6 +1062,20 @@ void tst_QtConcurrentFilter::filteredReducedInitialValue()
lambdaIntSumReduce, intInitial); lambdaIntSumReduce, intInitial);
CHECK_FAIL("lambda-lambda"); CHECK_FAIL("lambda-lambda");
// non-template sequences
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto future =
QtConcurrent::filteredReduced(list, keepEvenIntegers, intSumReduce, intInitial);
QCOMPARE(future.result(), intSum);
}
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto result = QtConcurrent::blockingFilteredReduced(list, keepEvenIntegers, intSumReduce,
intInitial);
QCOMPARE(result, intSum);
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::filteredReduced(std::vector { 1, 2, 3, 4 }, keepEvenIntegers, auto future = QtConcurrent::filteredReduced(std::vector { 1, 2, 3, 4 }, keepEvenIntegers,
@ -1127,6 +1216,20 @@ void tst_QtConcurrentFilter::filteredReducedInitialValueThreadPool()
lambdaSumReduce, intInitial); lambdaSumReduce, intInitial);
CHECK_FAIL("lambda-lambda"); CHECK_FAIL("lambda-lambda");
// non-template sequences
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto future =
QtConcurrent::filteredReduced(list, keepOddIntegers, intSumReduce, intInitial);
QCOMPARE(future.result(), intSum);
}
{
NonTemplateSequence list({ 1, 2, 3, 4 });
auto result = QtConcurrent::blockingFilteredReduced(list, keepOddIntegers, intSumReduce,
intInitial);
QCOMPARE(result, intSum);
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::filteredReduced(&pool, std::vector { 1, 2, 3, 4 }, auto future = QtConcurrent::filteredReduced(&pool, std::vector { 1, 2, 3, 4 },

View File

@ -201,6 +201,13 @@ void tst_QtConcurrentMap::map()
QCOMPARE(moveOnlyVector, MoveOnlyVector<int>({ 2, 4, 6 })); QCOMPARE(moveOnlyVector, MoveOnlyVector<int>({ 2, 4, 6 }));
} }
// non-template sequences
{
NonTemplateSequence list { 1, 2, 3 };
QtConcurrent::map(list, multiplyBy2InPlace).waitForFinished();
QCOMPARE(list, NonTemplateSequence({ 2, 4, 6 }));
}
#if 0 #if 0
// not allowed: map() with immutable sequences makes no sense // not allowed: map() with immutable sequences makes no sense
{ {
@ -331,6 +338,13 @@ void tst_QtConcurrentMap::blockingMap()
QCOMPARE(list, QList<int>() << 1 << 2 << 3); QCOMPARE(list, QList<int>() << 1 << 2 << 3);
} }
// non-template sequences
{
NonTemplateSequence list { 1, 2, 3 };
QtConcurrent::blockingMap(list, multiplyBy2InPlace);
QCOMPARE(list, NonTemplateSequence({ 2, 4, 6 }));
}
#if 0 #if 0
// not allowed: map() with immutable sequences makes no sense // not allowed: map() with immutable sequences makes no sense
{ {
@ -563,6 +577,17 @@ void tst_QtConcurrentMap::mapped()
CHECK_FAIL("member"); CHECK_FAIL("member");
#endif #endif
{
// non-template sequences
NonTemplateSequence list { 1, 2, 3 };
auto future = QtConcurrent::mapped(list, multiplyBy2);
QCOMPARE(future.results(), QList({ 2, 4, 6 }));
auto result = QtConcurrent::blockingMapped(list, multiplyBy2);
QCOMPARE(result, NonTemplateSequence({ 2, 4, 6 }));
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::mapped(std::vector { 1, 2, 3 }, multiplyBy2); auto future = QtConcurrent::mapped(std::vector { 1, 2, 3 }, multiplyBy2);
@ -666,6 +691,17 @@ void tst_QtConcurrentMap::mappedThreadPool()
testMappedThreadPool(&pool, intList, intListMultipiedBy3, lambdaMultiplyBy3); testMappedThreadPool(&pool, intList, intListMultipiedBy3, lambdaMultiplyBy3);
CHECK_FAIL("lambda"); CHECK_FAIL("lambda");
{
// non-template sequences
NonTemplateSequence list { 1, 2, 3 };
auto future = QtConcurrent::mapped(&pool, list, multiplyBy2);
QCOMPARE(future.results(), QList({ 2, 4, 6 }));
auto result = QtConcurrent::blockingMapped(&pool, list, multiplyBy2);
QCOMPARE(result, NonTemplateSequence({ 2, 4, 6 }));
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::mapped(&pool, std::vector { 1, 2, 3 }, multiplyBy2); auto future = QtConcurrent::mapped(&pool, std::vector { 1, 2, 3 }, multiplyBy2);
@ -880,6 +916,17 @@ void tst_QtConcurrentMap::mappedReduced()
testMappedReduced(intList, sumOfSquares, lambdaSquare, lambdaSumReduce); testMappedReduced(intList, sumOfSquares, lambdaSquare, lambdaSumReduce);
CHECK_FAIL("lambda-lambda"); CHECK_FAIL("lambda-lambda");
{
// non-template sequences
NonTemplateSequence list { 1, 2, 3 };
auto future = QtConcurrent::mappedReduced(list, multiplyBy2, intSumReduce);
QCOMPARE(future.result(), 12);
auto result = QtConcurrent::blockingMappedReduced(list, multiplyBy2, intSumReduce);
QCOMPARE(result, 12);
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::mappedReduced(std::vector { 1, 2, 3 }, intSquare, intSumReduce); auto future = QtConcurrent::mappedReduced(std::vector { 1, 2, 3 }, intSquare, intSumReduce);
@ -1019,6 +1066,17 @@ void tst_QtConcurrentMap::mappedReducedThreadPool()
testMappedReducedThreadPool(&pool, intList, sumOfCubes, lambdaCube, lambdaSumReduce); testMappedReducedThreadPool(&pool, intList, sumOfCubes, lambdaCube, lambdaSumReduce);
CHECK_FAIL("lambda-lambda"); CHECK_FAIL("lambda-lambda");
{
// non-template sequences
NonTemplateSequence list { 1, 2, 3 };
auto future = QtConcurrent::mappedReduced(&pool, list, multiplyBy2, intSumReduce);
QCOMPARE(future.result(), 12);
auto result = QtConcurrent::blockingMappedReduced(&pool, list, multiplyBy2, intSumReduce);
QCOMPARE(result, 12);
}
{ {
// rvalue sequences // rvalue sequences
auto future = auto future =
@ -1282,6 +1340,18 @@ void tst_QtConcurrentMap::mappedReducedInitialValue()
testMappedReducedInitialValue(intList, sumOfSquares, lambdaSquare, lambdaSumReduce, intInitial); testMappedReducedInitialValue(intList, sumOfSquares, lambdaSquare, lambdaSumReduce, intInitial);
CHECK_FAIL("lambda-lambda"); CHECK_FAIL("lambda-lambda");
{
// non-template sequences
NonTemplateSequence list { 1, 2, 3 };
auto future = QtConcurrent::mappedReduced(list, multiplyBy2, intSumReduce, intInitial);
QCOMPARE(future.result(), intInitial + 12);
auto result =
QtConcurrent::blockingMappedReduced(list, multiplyBy2, intSumReduce, intInitial);
QCOMPARE(result, intInitial + 12);
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::mappedReduced(std::vector { 1, 2, 3 }, intSquare, intSumReduce, auto future = QtConcurrent::mappedReduced(std::vector { 1, 2, 3 }, intSquare, intSumReduce,
@ -1419,6 +1489,19 @@ void tst_QtConcurrentMap::mappedReducedInitialValueThreadPool()
lambdaSumReduce, intInitial); lambdaSumReduce, intInitial);
CHECK_FAIL("lambda-lambda"); CHECK_FAIL("lambda-lambda");
{
// non-template sequences
NonTemplateSequence list { 1, 2, 3 };
auto future =
QtConcurrent::mappedReduced(&pool, list, multiplyBy2, intSumReduce, intInitial);
QCOMPARE(future.result(), intInitial + 12);
auto result = QtConcurrent::blockingMappedReduced(&pool, list, multiplyBy2, intSumReduce,
intInitial);
QCOMPARE(result, intInitial + 12);
}
{ {
// rvalue sequences // rvalue sequences
auto future = QtConcurrent::mappedReduced(&pool, std::vector { 1, 2, 3 }, intCube, auto future = QtConcurrent::mappedReduced(&pool, std::vector { 1, 2, 3 }, intCube,

View File

@ -28,6 +28,8 @@
#ifndef FUNCTIONS_H #ifndef FUNCTIONS_H
#define FUNCTIONS_H #define FUNCTIONS_H
#include <QList>
#include <vector> #include <vector>
bool keepEvenIntegers(const int &x) bool keepEvenIntegers(const int &x)
@ -196,4 +198,11 @@ private:
std::vector<T> data; std::vector<T> data;
}; };
struct NonTemplateSequence : public QList<int>
{
NonTemplateSequence() = default;
NonTemplateSequence(std::initializer_list<int> args) : QList(args) { }
};
#endif #endif