QtConcurrent: prevent conversion of ReduceOption to initial value
QtConcurrent map- and filter-reduce functions take an initial value, which can be of any type that is convertable to the result type. The side-effect of this is that the enum values passed as ReduceOptions can be treated as an initial value (if they are convertable to the result type) which will result into a wrong overload call. To avoid this, added additional check to make sure that the initial value type doesn't match with ReduceOption enum. Note that this required including the qtconcurrentreducekernel.h header in qtconcurrentfunctionwrappers.h (which contains compiler checks for QtConcurrent) for accessing ReduceOption enum, so I had to get rid of qtconcurrentfunctionwrappers.h include from qtconcurrentreducekernel.h to avoid circular header includes. This, in turn, required moving the QtPrivate::SequenceHolder helper type to qtconcurrentreducekernel.h, which didn't belong to qtconcurrentfunctionwrappers.h anyway. Pick-to: 6.3 6.2 Fixes: QTBUG-102999 Change-Id: Ieaa8ef2e4bd82ce2ada2e0af9a47b87b51d59e87 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Marc Mutz <marc.mutz@qt.io>
This commit is contained in:
parent
fa01e0bd71
commit
bd1023a824
@ -73,7 +73,8 @@ template <typename ResultType, typename Sequence, typename KeepFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> filteredReduced(QThreadPool *pool,
|
QFuture<ResultType> filteredReduced(QThreadPool *pool,
|
||||||
Sequence &&sequence,
|
Sequence &&sequence,
|
||||||
@ -95,7 +96,8 @@ template <typename ResultType, typename Sequence, typename KeepFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> filteredReduced(Sequence &&sequence,
|
QFuture<ResultType> filteredReduced(Sequence &&sequence,
|
||||||
KeepFunctor &&keep,
|
KeepFunctor &&keep,
|
||||||
@ -144,7 +146,8 @@ template <typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
|||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<QtPrivate::isInvocable<KeepFunctor, Sequence>::value, int> = 0,
|
std::enable_if_t<QtPrivate::isInvocable<KeepFunctor, Sequence>::value, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
QFuture<ResultType> filteredReduced(QThreadPool *pool,
|
QFuture<ResultType> filteredReduced(QThreadPool *pool,
|
||||||
Sequence &&sequence,
|
Sequence &&sequence,
|
||||||
KeepFunctor &&keep,
|
KeepFunctor &&keep,
|
||||||
@ -163,7 +166,8 @@ template <typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
|||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<QtPrivate::isInvocable<KeepFunctor, Sequence>::value, int> = 0,
|
std::enable_if_t<QtPrivate::isInvocable<KeepFunctor, Sequence>::value, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
QFuture<ResultType> filteredReduced(Sequence &&sequence,
|
QFuture<ResultType> filteredReduced(Sequence &&sequence,
|
||||||
KeepFunctor &&keep,
|
KeepFunctor &&keep,
|
||||||
ReduceFunctor &&reduce,
|
ReduceFunctor &&reduce,
|
||||||
@ -211,7 +215,8 @@ template <typename ResultType, typename Iterator, typename KeepFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> filteredReduced(QThreadPool *pool,
|
QFuture<ResultType> filteredReduced(QThreadPool *pool,
|
||||||
Iterator begin,
|
Iterator begin,
|
||||||
@ -233,7 +238,8 @@ template <typename ResultType, typename Iterator, typename KeepFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> filteredReduced(Iterator begin,
|
QFuture<ResultType> filteredReduced(Iterator begin,
|
||||||
Iterator end,
|
Iterator end,
|
||||||
@ -281,7 +287,8 @@ QFuture<ResultType> filteredReduced(Iterator begin,
|
|||||||
template <typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
template <typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
QFuture<ResultType> filteredReduced(QThreadPool *pool,
|
QFuture<ResultType> filteredReduced(QThreadPool *pool,
|
||||||
Iterator begin,
|
Iterator begin,
|
||||||
Iterator end,
|
Iterator end,
|
||||||
@ -300,7 +307,8 @@ template <typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
|||||||
std::enable_if_t<QtPrivate::isIterator_v<Iterator>, int> = 0,
|
std::enable_if_t<QtPrivate::isIterator_v<Iterator>, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
QFuture<ResultType> filteredReduced(Iterator begin,
|
QFuture<ResultType> filteredReduced(Iterator begin,
|
||||||
Iterator end,
|
Iterator end,
|
||||||
KeepFunctor &&keep,
|
KeepFunctor &&keep,
|
||||||
@ -400,7 +408,8 @@ template <typename ResultType, typename Sequence, typename KeepFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingFilteredReduced(QThreadPool *pool,
|
ResultType blockingFilteredReduced(QThreadPool *pool,
|
||||||
Sequence &&sequence,
|
Sequence &&sequence,
|
||||||
@ -423,7 +432,8 @@ template <typename ResultType, typename Sequence, typename KeepFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingFilteredReduced(Sequence &&sequence,
|
ResultType blockingFilteredReduced(Sequence &&sequence,
|
||||||
KeepFunctor &&keep,
|
KeepFunctor &&keep,
|
||||||
@ -475,7 +485,8 @@ template <typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
|||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<QtPrivate::isInvocable<KeepFunctor, Sequence>::value, int> = 0,
|
std::enable_if_t<QtPrivate::isInvocable<KeepFunctor, Sequence>::value, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
ResultType blockingFilteredReduced(QThreadPool *pool,
|
ResultType blockingFilteredReduced(QThreadPool *pool,
|
||||||
Sequence &&sequence,
|
Sequence &&sequence,
|
||||||
KeepFunctor &&keep,
|
KeepFunctor &&keep,
|
||||||
@ -495,7 +506,8 @@ template <typename Sequence, typename KeepFunctor, typename ReduceFunctor,
|
|||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<QtPrivate::isInvocable<KeepFunctor, Sequence>::value, int> = 0,
|
std::enable_if_t<QtPrivate::isInvocable<KeepFunctor, Sequence>::value, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
ResultType blockingFilteredReduced(Sequence &&sequence,
|
ResultType blockingFilteredReduced(Sequence &&sequence,
|
||||||
KeepFunctor &&keep,
|
KeepFunctor &&keep,
|
||||||
ReduceFunctor &&reduce,
|
ReduceFunctor &&reduce,
|
||||||
@ -547,7 +559,8 @@ template <typename ResultType, typename Iterator, typename KeepFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingFilteredReduced(QThreadPool *pool,
|
ResultType blockingFilteredReduced(QThreadPool *pool,
|
||||||
Iterator begin,
|
Iterator begin,
|
||||||
@ -570,7 +583,8 @@ template <typename ResultType, typename Iterator, typename KeepFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingFilteredReduced(Iterator begin,
|
ResultType blockingFilteredReduced(Iterator begin,
|
||||||
Iterator end,
|
Iterator end,
|
||||||
@ -621,7 +635,8 @@ ResultType blockingFilteredReduced(Iterator begin,
|
|||||||
template <typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
template <typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
ResultType blockingFilteredReduced(QThreadPool *pool,
|
ResultType blockingFilteredReduced(QThreadPool *pool,
|
||||||
Iterator begin,
|
Iterator begin,
|
||||||
Iterator end, KeepFunctor &&keep,
|
Iterator end, KeepFunctor &&keep,
|
||||||
@ -640,7 +655,8 @@ template <typename Iterator, typename KeepFunctor, typename ReduceFunctor,
|
|||||||
std::enable_if_t<QtPrivate::isIterator_v<Iterator>, int> = 0,
|
std::enable_if_t<QtPrivate::isIterator_v<Iterator>, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
ResultType blockingFilteredReduced(Iterator begin,
|
ResultType blockingFilteredReduced(Iterator begin,
|
||||||
Iterator end,
|
Iterator end,
|
||||||
KeepFunctor &&keep,
|
KeepFunctor &&keep,
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
#define QTCONCURRENT_FUNCTIONWRAPPERS_H
|
#define QTCONCURRENT_FUNCTIONWRAPPERS_H
|
||||||
|
|
||||||
#include <QtConcurrent/qtconcurrentcompilertest.h>
|
#include <QtConcurrent/qtconcurrentcompilertest.h>
|
||||||
|
#include <QtConcurrent/qtconcurrentreducekernel.h>
|
||||||
#include <QtCore/qfuture.h>
|
#include <QtCore/qfuture.h>
|
||||||
|
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
@ -121,6 +122,11 @@ inline constexpr bool isIterator_v<T, std::void_t<typename std::iterator_traits<
|
|||||||
template <class Callable, class Sequence>
|
template <class Callable, class Sequence>
|
||||||
using isInvocable = std::is_invocable<Callable, typename std::decay_t<Sequence>::value_type>;
|
using isInvocable = std::is_invocable<Callable, typename std::decay_t<Sequence>::value_type>;
|
||||||
|
|
||||||
|
template <class InitialValueType, class ResultType>
|
||||||
|
inline constexpr bool isInitialValueCompatible_v = std::conjunction_v<
|
||||||
|
std::is_convertible<InitialValueType, ResultType>,
|
||||||
|
std::negation<std::is_same<std::decay_t<InitialValueType>, QtConcurrent::ReduceOption>>>;
|
||||||
|
|
||||||
template<class Callable, class Enable = void>
|
template<class Callable, class Enable = void>
|
||||||
struct ReduceResultTypeHelper
|
struct ReduceResultTypeHelper
|
||||||
{
|
{
|
||||||
@ -163,14 +169,6 @@ struct MapSequenceResultType<InputSequence<T...>, MapFunctor>
|
|||||||
|
|
||||||
#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER
|
#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER
|
||||||
|
|
||||||
template<typename Sequence>
|
|
||||||
struct SequenceHolder
|
|
||||||
{
|
|
||||||
SequenceHolder(const Sequence &s) : sequence(s) { }
|
|
||||||
SequenceHolder(Sequence &&s) : sequence(std::move(s)) { }
|
|
||||||
Sequence sequence;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace QtPrivate.
|
} // namespace QtPrivate.
|
||||||
|
|
||||||
|
|
||||||
|
@ -77,7 +77,8 @@ template <typename ResultType, typename Sequence, typename MapFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> mappedReduced(QThreadPool *pool,
|
QFuture<ResultType> mappedReduced(QThreadPool *pool,
|
||||||
Sequence &&sequence,
|
Sequence &&sequence,
|
||||||
@ -98,7 +99,8 @@ template <typename ResultType, typename Sequence, typename MapFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> mappedReduced(Sequence &&sequence,
|
QFuture<ResultType> mappedReduced(Sequence &&sequence,
|
||||||
MapFunctor &&map,
|
MapFunctor &&map,
|
||||||
@ -149,7 +151,8 @@ template <typename Sequence, typename MapFunctor, typename ReduceFunctor, typena
|
|||||||
template <typename Sequence, typename MapFunctor, typename ReduceFunctor, typename InitialValueType,
|
template <typename Sequence, typename MapFunctor, typename ReduceFunctor, typename InitialValueType,
|
||||||
std::enable_if_t<QtPrivate::isInvocable<MapFunctor, Sequence>::value, int> = 0,
|
std::enable_if_t<QtPrivate::isInvocable<MapFunctor, Sequence>::value, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> mappedReduced(QThreadPool *pool,
|
QFuture<ResultType> mappedReduced(QThreadPool *pool,
|
||||||
Sequence &&sequence,
|
Sequence &&sequence,
|
||||||
@ -172,7 +175,8 @@ template <typename Sequence, typename MapFunctor, typename ReduceFunctor, typena
|
|||||||
template <typename Sequence, typename MapFunctor, typename ReduceFunctor, typename InitialValueType,
|
template <typename Sequence, typename MapFunctor, typename ReduceFunctor, typename InitialValueType,
|
||||||
std::enable_if_t<QtPrivate::isInvocable<MapFunctor, Sequence>::value, int> = 0,
|
std::enable_if_t<QtPrivate::isInvocable<MapFunctor, Sequence>::value, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> mappedReduced(Sequence &&sequence,
|
QFuture<ResultType> mappedReduced(Sequence &&sequence,
|
||||||
MapFunctor &&map,
|
MapFunctor &&map,
|
||||||
@ -221,7 +225,8 @@ template <typename ResultType, typename Iterator, typename MapFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> mappedReduced(QThreadPool *pool,
|
QFuture<ResultType> mappedReduced(QThreadPool *pool,
|
||||||
Iterator begin,
|
Iterator begin,
|
||||||
@ -243,7 +248,8 @@ template <typename ResultType, typename Iterator, typename MapFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> mappedReduced(Iterator begin,
|
QFuture<ResultType> mappedReduced(Iterator begin,
|
||||||
Iterator end,
|
Iterator end,
|
||||||
@ -295,7 +301,8 @@ template <typename Iterator, typename MapFunctor, typename ReduceFunctor, typena
|
|||||||
template <typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
template <typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> mappedReduced(QThreadPool *pool,
|
QFuture<ResultType> mappedReduced(QThreadPool *pool,
|
||||||
Iterator begin,
|
Iterator begin,
|
||||||
@ -319,7 +326,8 @@ template<typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
|||||||
std::enable_if_t<QtPrivate::isIterator_v<Iterator>, int> = 0,
|
std::enable_if_t<QtPrivate::isIterator_v<Iterator>, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
QFuture<ResultType> mappedReduced(Iterator begin,
|
QFuture<ResultType> mappedReduced(Iterator begin,
|
||||||
Iterator end,
|
Iterator end,
|
||||||
@ -447,7 +455,8 @@ template <typename ResultType, typename Sequence, typename MapFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingMappedReduced(QThreadPool *pool,
|
ResultType blockingMappedReduced(QThreadPool *pool,
|
||||||
Sequence &&sequence,
|
Sequence &&sequence,
|
||||||
@ -470,7 +479,8 @@ template <typename ResultType, typename Sequence, typename MapFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Sequence, typename MapFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingMappedReduced(Sequence &&sequence,
|
ResultType blockingMappedReduced(Sequence &&sequence,
|
||||||
MapFunctor &&map,
|
MapFunctor &&map,
|
||||||
@ -526,7 +536,8 @@ template <typename MapFunctor, typename ReduceFunctor, typename Sequence, typena
|
|||||||
template <typename MapFunctor, typename ReduceFunctor, typename Sequence, typename InitialValueType,
|
template <typename MapFunctor, typename ReduceFunctor, typename Sequence, typename InitialValueType,
|
||||||
std::enable_if_t<QtPrivate::isInvocable<MapFunctor, Sequence>::value, int> = 0,
|
std::enable_if_t<QtPrivate::isInvocable<MapFunctor, Sequence>::value, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingMappedReduced(QThreadPool *pool,
|
ResultType blockingMappedReduced(QThreadPool *pool,
|
||||||
Sequence &&sequence,
|
Sequence &&sequence,
|
||||||
@ -550,7 +561,8 @@ template <typename MapFunctor, typename ReduceFunctor, typename Sequence, typena
|
|||||||
template<typename MapFunctor, typename ReduceFunctor, typename Sequence, typename InitialValueType,
|
template<typename MapFunctor, typename ReduceFunctor, typename Sequence, typename InitialValueType,
|
||||||
std::enable_if_t<QtPrivate::isInvocable<MapFunctor, Sequence>::value, int> = 0,
|
std::enable_if_t<QtPrivate::isInvocable<MapFunctor, Sequence>::value, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingMappedReduced(Sequence &&sequence,
|
ResultType blockingMappedReduced(Sequence &&sequence,
|
||||||
MapFunctor &&map,
|
MapFunctor &&map,
|
||||||
@ -602,7 +614,8 @@ template <typename ResultType, typename Iterator, typename MapFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingMappedReduced(QThreadPool *pool,
|
ResultType blockingMappedReduced(QThreadPool *pool,
|
||||||
Iterator begin,
|
Iterator begin,
|
||||||
@ -626,7 +639,8 @@ template <typename ResultType, typename Iterator, typename MapFunctor, typename
|
|||||||
#else
|
#else
|
||||||
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
template <typename ResultType, typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingMappedReduced(Iterator begin,
|
ResultType blockingMappedReduced(Iterator begin,
|
||||||
Iterator end,
|
Iterator end,
|
||||||
@ -681,7 +695,8 @@ template <typename Iterator, typename MapFunctor, typename ReduceFunctor, typena
|
|||||||
template <typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
template <typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingMappedReduced(QThreadPool *pool,
|
ResultType blockingMappedReduced(QThreadPool *pool,
|
||||||
Iterator begin,
|
Iterator begin,
|
||||||
@ -706,7 +721,8 @@ template <typename Iterator, typename MapFunctor, typename ReduceFunctor,
|
|||||||
std::enable_if_t<QtPrivate::isIterator_v<Iterator>, int> = 0,
|
std::enable_if_t<QtPrivate::isIterator_v<Iterator>, int> = 0,
|
||||||
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
typename ResultType = typename QtPrivate::ReduceResultTypeHelper<ReduceFunctor>::type,
|
||||||
typename InitialValueType,
|
typename InitialValueType,
|
||||||
std::enable_if_t<std::is_convertible_v<InitialValueType, ResultType>, int> = 0>
|
std::enable_if_t<QtPrivate::isInitialValueCompatible_v<InitialValueType, ResultType>,
|
||||||
|
int> = 0>
|
||||||
#endif
|
#endif
|
||||||
ResultType blockingMappedReduced(Iterator begin,
|
ResultType blockingMappedReduced(Iterator begin,
|
||||||
Iterator end,
|
Iterator end,
|
||||||
|
@ -5,7 +5,6 @@
|
|||||||
#define QTCONCURRENT_REDUCEKERNEL_H
|
#define QTCONCURRENT_REDUCEKERNEL_H
|
||||||
|
|
||||||
#include <QtConcurrent/qtconcurrent_global.h>
|
#include <QtConcurrent/qtconcurrent_global.h>
|
||||||
#include <QtConcurrent/qtconcurrentfunctionwrappers.h>
|
|
||||||
|
|
||||||
#if !defined(QT_NO_CONCURRENT) || defined(Q_CLANG_QDOC)
|
#if !defined(QT_NO_CONCURRENT) || defined(Q_CLANG_QDOC)
|
||||||
|
|
||||||
@ -20,6 +19,17 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
namespace QtPrivate {
|
||||||
|
|
||||||
|
template<typename Sequence>
|
||||||
|
struct SequenceHolder
|
||||||
|
{
|
||||||
|
SequenceHolder(const Sequence &s) : sequence(s) { }
|
||||||
|
SequenceHolder(Sequence &&s) : sequence(std::move(s)) { }
|
||||||
|
Sequence sequence;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace QtConcurrent {
|
namespace QtConcurrent {
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ private slots:
|
|||||||
void filteredReducedInitialValueThreadPool();
|
void filteredReducedInitialValueThreadPool();
|
||||||
void filteredReducedInitialValueWithMoveOnlyCallables();
|
void filteredReducedInitialValueWithMoveOnlyCallables();
|
||||||
void filteredReducedDifferentTypeInitialValue();
|
void filteredReducedDifferentTypeInitialValue();
|
||||||
|
void filteredReduceOptionConvertableToResultType();
|
||||||
void resultAt();
|
void resultAt();
|
||||||
void incrementalResults();
|
void incrementalResults();
|
||||||
void noDetach();
|
void noDetach();
|
||||||
@ -1338,6 +1339,56 @@ void tst_QtConcurrentFilter::filteredReducedDifferentTypeInitialValue()
|
|||||||
CHECK_FAIL("lambda-lambda");
|
CHECK_FAIL("lambda-lambda");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QtConcurrentFilter::filteredReduceOptionConvertableToResultType()
|
||||||
|
{
|
||||||
|
const QList<int> intList { 1, 2, 3 };
|
||||||
|
const int sum = 4;
|
||||||
|
QThreadPool p;
|
||||||
|
ReduceOption ro = OrderedReduce;
|
||||||
|
|
||||||
|
// With container
|
||||||
|
QCOMPARE(QtConcurrent::filteredReduced(intList, keepOddIntegers, intSumReduce, ro).result(),
|
||||||
|
sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingFilteredReduced(intList, keepOddIntegers, intSumReduce, ro),
|
||||||
|
sum);
|
||||||
|
|
||||||
|
// With iterators
|
||||||
|
QCOMPARE(QtConcurrent::filteredReduced(intList.begin(), intList.end(), keepOddIntegers,
|
||||||
|
intSumReduce, ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingFilteredReduced(intList.begin(), intList.end(), keepOddIntegers,
|
||||||
|
intSumReduce, ro), sum);
|
||||||
|
|
||||||
|
// With custom QThreadPool;
|
||||||
|
QCOMPARE(QtConcurrent::filteredReduced(&p, intList, keepOddIntegers, intSumReduce, ro).result(),
|
||||||
|
sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingFilteredReduced(&p, intList, keepOddIntegers, intSumReduce, ro),
|
||||||
|
sum);
|
||||||
|
QCOMPARE(QtConcurrent::filteredReduced(&p, intList.begin(), intList.end(), keepOddIntegers,
|
||||||
|
intSumReduce, ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingFilteredReduced(&p, intList.begin(), intList.end(),
|
||||||
|
keepOddIntegers, intSumReduce, ro), sum);
|
||||||
|
|
||||||
|
// The same as above, but specify the result type explicitly (this invokes different overloads)
|
||||||
|
QCOMPARE(QtConcurrent::filteredReduced<int>(intList, keepOddIntegers, intSumReduce,
|
||||||
|
ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingFilteredReduced<int>(intList, keepOddIntegers, intSumReduce, ro),
|
||||||
|
sum);
|
||||||
|
|
||||||
|
QCOMPARE(QtConcurrent::filteredReduced<int>(intList.begin(), intList.end(), keepOddIntegers,
|
||||||
|
intSumReduce, ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingFilteredReduced<int>(intList.begin(), intList.end(),
|
||||||
|
keepOddIntegers, intSumReduce, ro), sum);
|
||||||
|
|
||||||
|
QCOMPARE(QtConcurrent::filteredReduced<int>(&p, intList, keepOddIntegers, intSumReduce,
|
||||||
|
ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingFilteredReduced<int>(&p, intList, keepOddIntegers, intSumReduce,
|
||||||
|
ro), sum);
|
||||||
|
QCOMPARE(QtConcurrent::filteredReduced<int>(&p, intList.begin(), intList.end(), keepOddIntegers,
|
||||||
|
intSumReduce, ro).result(),sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingFilteredReduced<int>(&p, intList.begin(), intList.end(),
|
||||||
|
keepOddIntegers, intSumReduce, ro), sum);
|
||||||
|
}
|
||||||
|
|
||||||
bool filterfn(int i)
|
bool filterfn(int i)
|
||||||
{
|
{
|
||||||
return (i % 2);
|
return (i % 2);
|
||||||
|
@ -30,6 +30,7 @@ private slots:
|
|||||||
void mappedReducedInitialValueThreadPool();
|
void mappedReducedInitialValueThreadPool();
|
||||||
void mappedReducedInitialValueWithMoveOnlyCallable();
|
void mappedReducedInitialValueWithMoveOnlyCallable();
|
||||||
void mappedReducedDifferentTypeInitialValue();
|
void mappedReducedDifferentTypeInitialValue();
|
||||||
|
void mappedReduceOptionConvertableToResultType();
|
||||||
void assignResult();
|
void assignResult();
|
||||||
void functionOverloads();
|
void functionOverloads();
|
||||||
void noExceptFunctionOverloads();
|
void noExceptFunctionOverloads();
|
||||||
@ -1605,6 +1606,51 @@ void tst_QtConcurrentMap::mappedReducedDifferentTypeInitialValue()
|
|||||||
CHECK_FAIL("lambda-lambda");
|
CHECK_FAIL("lambda-lambda");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QtConcurrentMap::mappedReduceOptionConvertableToResultType()
|
||||||
|
{
|
||||||
|
const QList<int> intList { 1, 2, 3 };
|
||||||
|
const int sum = 12;
|
||||||
|
QThreadPool p;
|
||||||
|
ReduceOption ro = OrderedReduce;
|
||||||
|
|
||||||
|
// With container
|
||||||
|
QCOMPARE(QtConcurrent::mappedReduced(intList, multiplyBy2, intSumReduce, ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingMappedReduced(intList, multiplyBy2, intSumReduce, ro), sum);
|
||||||
|
|
||||||
|
// With iterators
|
||||||
|
QCOMPARE(QtConcurrent::mappedReduced(intList.begin(), intList.end(), multiplyBy2, intSumReduce,
|
||||||
|
ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingMappedReduced(intList.begin(), intList.end(), multiplyBy2,
|
||||||
|
intSumReduce, ro), sum);
|
||||||
|
|
||||||
|
// With custom QThreadPool;
|
||||||
|
QCOMPARE(QtConcurrent::mappedReduced(&p, intList, multiplyBy2, intSumReduce, ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingMappedReduced(&p, intList, multiplyBy2, intSumReduce, ro), sum);
|
||||||
|
QCOMPARE(QtConcurrent::mappedReduced(&p, intList.begin(), intList.end(), multiplyBy2,
|
||||||
|
intSumReduce, ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingMappedReduced(&p, intList.begin(), intList.end(), multiplyBy2,
|
||||||
|
intSumReduce, ro), sum);
|
||||||
|
|
||||||
|
// The same as above, but specify the result type explicitly (this invokes different overloads)
|
||||||
|
QCOMPARE(QtConcurrent::mappedReduced<int>(intList, multiplyBy2, intSumReduce, ro).result(),
|
||||||
|
sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingMappedReduced<int>(intList, multiplyBy2, intSumReduce, ro), sum);
|
||||||
|
|
||||||
|
QCOMPARE(QtConcurrent::mappedReduced<int>(intList.begin(), intList.end(), multiplyBy2,
|
||||||
|
intSumReduce, ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingMappedReduced<int>(intList.begin(), intList.end(), multiplyBy2,
|
||||||
|
intSumReduce, ro), sum);
|
||||||
|
|
||||||
|
QCOMPARE(QtConcurrent::mappedReduced<int>(&p, intList, multiplyBy2, intSumReduce, ro).result(),
|
||||||
|
sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingMappedReduced<int>(&p, intList, multiplyBy2, intSumReduce, ro),
|
||||||
|
sum);
|
||||||
|
QCOMPARE(QtConcurrent::mappedReduced<int>(&p, intList.begin(), intList.end(), multiplyBy2,
|
||||||
|
intSumReduce, ro).result(), sum);
|
||||||
|
QCOMPARE(QtConcurrent::blockingMappedReduced<int>(&p, intList.begin(), intList.end(),
|
||||||
|
multiplyBy2, intSumReduce, ro), sum);
|
||||||
|
}
|
||||||
|
|
||||||
int sleeper(int val)
|
int sleeper(int val)
|
||||||
{
|
{
|
||||||
QTest::qSleep(100);
|
QTest::qSleep(100);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user