diff options
-rw-r--r-- | src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentfilter.cpp | 56 | ||||
-rw-r--r-- | src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp | 37 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentcompilertest.h | 28 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentfilter.cpp | 23 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentfilter.h | 79 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentfilterkernel.h | 20 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentfunctionwrappers.h | 272 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentmap.cpp | 51 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentmap.h | 132 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentmapkernel.h | 25 | ||||
-rw-r--r-- | src/concurrent/qtconcurrentreducekernel.h | 2 | ||||
-rw-r--r-- | tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp | 343 | ||||
-rw-r--r-- | tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp | 675 | ||||
-rw-r--r-- | tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp | 6 |
14 files changed, 1344 insertions, 405 deletions
diff --git a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentfilter.cpp b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentfilter.cpp index 3cc1fe836c..ef87a60080 100644 --- a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentfilter.cpp +++ b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentfilter.cpp @@ -158,8 +158,6 @@ struct StartsWith StartsWith(const QString &string) : m_string(string) { } - typedef bool result_type; - bool operator()(const QString &testString) { return testString.startsWith(m_string); @@ -183,3 +181,57 @@ QFuture<QString> fooString = StartsWith(QLatin1String("Foo")), StringTransform()); //! [14] + +//! [15] +// keep only even integers +QVector<int> vector { 1, 2, 3, 4 }; +QtConcurrent::blockingFilter(vector, [](int n) { return (n & 1) == 0; }); + +// retrieve only even integers +QVector<int> vector2 { 1, 2, 3, 4 }; +QFuture<int> future = QtConcurrent::filtered(vector2, [](int x) { + return (x & 1) == 0; +}); +QVector<int> results = future.results(); + +// add up all even integers +QVector<int> vector3 { 1, 2, 3, 4 }; +int sum = QtConcurrent::filteredReduced<int>(vector3, + [](int x) { + return (x & 1) == 0; + }, + [](int &sum, int x) { + sum += x; + } +); +//! [15] + +//! [16] +void intSumReduce(int &sum, int x) +{ + sum += x; +} + +QVector<int> vector { 1, 2, 3, 4 }; +int sum = QtConcurrent::filteredReduced(vector, + [] (int x) { + return (x & 1) == 0; + }, + intSumReduce +); +//! [16] + +//! [17] +bool keepEvenIntegers(int x) +{ + return (x & 1) == 0; +} + +QVector<int> vector { 1, 2, 3, 4 }; +int sum = QtConcurrent::filteredReduced<int>(vector, + keepEvenIntegers, + [](int &sum, int x) { + sum += x; + } +); +//! [17] diff --git a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp index fc574302d2..dd3e0103bb 100644 --- a/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp +++ b/src/concurrent/doc/snippets/code/src_concurrent_qtconcurrentmap.cpp @@ -130,7 +130,8 @@ QFuture<void> squeezedStrings = QtConcurrent::map(strings, &QString::squeeze); // Swap the rgb values of all pixels on a list of images. QList<QImage> images = ...; -QFuture<QImage> bgrImages = QtConcurrent::mapped(images, &QImage::rgbSwapped); +QFuture<QImage> bgrImages = QtConcurrent::mapped(images, + static_cast<QImage (QImage::*)() const &>(&QImage::rgbSwapped)); // Create a set of the lengths of all strings in a list. QStringList strings = ...; @@ -197,3 +198,37 @@ struct Scaled QList<QImage> images = ...; QFuture<QImage> thumbnails = QtConcurrent::mapped(images, Scaled(100)); //! [14] + +//! [15] +QVector<int> vector { 1, 2, 3, 4 }; +QtConcurrent::blockingMap(vector, [](int &x) { x *= 2; }); + +int size = 100; +QVector<QImage> images = ...; + +QVector<QImage> thumbnails = QtConcurrent::mapped(images, + [&size](const QImage &image) { + return image.scaled(size, size); + } + ).results(); +//! [15] + +//! [16] +QVector<QImage> collage = QtConcurrent::mappedReduced(images, + [&size](const QImage &image) { + return image.scaled(size, size); + }, + addToCollage + ).results(); +//! [16] + +//! [17] +QVector<QImage> collage = QtConcurrent::mappedReduced<QImage>(images, + [&size](const QImage &image) { + return image.scaled(size, size); + }, + [](QImage &result, const QImage &value) { + // do some transformation + } + ).results(); +//! [17] diff --git a/src/concurrent/qtconcurrentcompilertest.h b/src/concurrent/qtconcurrentcompilertest.h index 72cf1670a0..8292d5c504 100644 --- a/src/concurrent/qtconcurrentcompilertest.h +++ b/src/concurrent/qtconcurrentcompilertest.h @@ -48,16 +48,26 @@ QT_BEGIN_NAMESPACE namespace QtPrivate { -template<class T> -class HasResultType { - typedef char Yes; - typedef void *No; - template<typename U> static Yes test(int, const typename U::result_type * = nullptr); - template<typename U> static No test(double); -public: - enum { Value = (sizeof(test<T>(0)) == sizeof(Yes)) }; -}; + template <class T, typename = void> + struct IsIterable : std::false_type {}; + template <class T> + struct IsIterable<T, std::void_t<decltype(std::begin(std::declval<T>())), + decltype(std::end(std::declval<T>()))>> + : std::true_type + { }; + template <class T> + inline constexpr bool IsIterableValue = IsIterable<T>::value; + + template <class T, typename = void> + struct IsDereferenceable : std::false_type {}; + template <class T> + struct IsDereferenceable<T, std::void_t<decltype(*std::declval<T>())>> + : std::true_type + { }; + + template <class T> + inline constexpr bool IsDereferenceableValue = IsDereferenceable<T>::value; } QT_END_NAMESPACE diff --git a/src/concurrent/qtconcurrentfilter.cpp b/src/concurrent/qtconcurrentfilter.cpp index bac8ac59fc..789188911e 100644 --- a/src/concurrent/qtconcurrentfilter.cpp +++ b/src/concurrent/qtconcurrentfilter.cpp @@ -144,8 +144,7 @@ QtConcurrent::filter(), QtConcurrent::filtered(), and QtConcurrent::filteredReduced() accept function objects for the filter function. These function objects can be used to - add state to a function call. The result_type typedef must define the - result type of the function call operator: + add state to a function call: \snippet code/src_concurrent_qtconcurrentfilter.cpp 13 @@ -155,6 +154,26 @@ \snippet code/src_concurrent_qtconcurrentfilter.cpp 14 + \section2 Using Lambda Expressions + + QtConcurrent::filter(), QtConcurrent::filtered(), and + QtConcurrent::filteredReduced() accept lambda expressions for the filter and + reduce function: + + \snippet code/src_concurrent_qtconcurrentfilter.cpp 15 + + When using QtConcurrent::filteredReduced() or + QtConcurrent::blockingFilteredReduced(), you can mix the use of normal + functions, member functions and lambda expressions freely. + + \snippet code/src_concurrent_qtconcurrentfilter.cpp 16 + + For the reduce function, lambda expressions are not directly supported. + Lambda expressions can, however, be used when the type of the reduction + result is explicitly specified: + + \snippet code/src_concurrent_qtconcurrentfilter.cpp 17 + \section2 Wrapping Functions that Take Multiple Arguments If you want to use a filter function takes more than one argument, you can diff --git a/src/concurrent/qtconcurrentfilter.h b/src/concurrent/qtconcurrentfilter.h index 4c7d1ee7e5..df4c9ed384 100644 --- a/src/concurrent/qtconcurrentfilter.h +++ b/src/concurrent/qtconcurrentfilter.h @@ -63,7 +63,7 @@ ThreadEngineStarter<void> filterInternal(Sequence &sequence, KeepFunctor keep, R template <typename Sequence, typename KeepFunctor> QFuture<void> filter(Sequence &sequence, KeepFunctor keep) { - return filterInternal(sequence, QtPrivate::createFunctionWrapper(keep), QtPrivate::PushBackWrapper()); + return filterInternal(sequence, keep, QtPrivate::PushBackWrapper()); } // filteredReduced() on sequences @@ -73,7 +73,7 @@ QFuture<ResultType> filteredReduced(const Sequence &sequence, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced<ResultType>(sequence, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options); + return startFilteredReduced<ResultType>(sequence, keep, reduce, options); } template <typename ResultType, typename Sequence, typename KeepFunctor, typename ReduceFunctor, @@ -85,8 +85,8 @@ QFuture<ResultType> filteredReduced(const Sequence &sequence, KeepFunctor keep, | SequentialReduce)) { return startFilteredReduced<ResultType>( - sequence, QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + sequence, keep, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options); } @@ -99,8 +99,8 @@ QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> filtere { return startFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> (sequence, - QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + keep, + reduce, options); } @@ -114,8 +114,8 @@ QFuture<ResultType> filteredReduced(const Sequence &sequence, KeepFunctor keep, | SequentialReduce)) { return startFilteredReduced<ResultType>( - sequence, QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + sequence, keep, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options); } #endif @@ -128,7 +128,7 @@ QFuture<ResultType> filteredReduced(Iterator begin, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced<ResultType>(begin, end, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options); + return startFilteredReduced<ResultType>(begin, end, keep, reduce, options); } template <typename ResultType, typename Iterator, typename KeepFunctor, typename ReduceFunctor, @@ -140,8 +140,8 @@ QFuture<ResultType> filteredReduced(Iterator begin, Iterator end, KeepFunctor ke | SequentialReduce)) { return startFilteredReduced<ResultType>( - begin, end, QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + begin, end, keep, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options); } @@ -155,8 +155,8 @@ QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> filtere { return startFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> (begin, end, - QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + keep, + reduce, options); } @@ -170,8 +170,8 @@ QFuture<ResultType> filteredReduced(Iterator begin, Iterator end, KeepFunctor ke | SequentialReduce)) { return startFilteredReduced<ResultType>( - begin, end, QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + begin, end, keep, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options); } #endif @@ -180,21 +180,21 @@ QFuture<ResultType> filteredReduced(Iterator begin, Iterator end, KeepFunctor ke template <typename Sequence, typename KeepFunctor> QFuture<typename Sequence::value_type> filtered(const Sequence &sequence, KeepFunctor keep) { - return startFiltered(sequence, QtPrivate::createFunctionWrapper(keep)); + return startFiltered(sequence, keep); } // filtered() on iterators template <typename Iterator, typename KeepFunctor> QFuture<typename qValueType<Iterator>::value_type> filtered(Iterator begin, Iterator end, KeepFunctor keep) { - return startFiltered(begin, end, QtPrivate::createFunctionWrapper(keep)); + return startFiltered(begin, end, keep); } // blocking filter() on sequences template <typename Sequence, typename KeepFunctor> void blockingFilter(Sequence &sequence, KeepFunctor keep) { - filterInternal(sequence, QtPrivate::createFunctionWrapper(keep), QtPrivate::PushBackWrapper()).startBlocking(); + filterInternal(sequence, keep, QtPrivate::PushBackWrapper()).startBlocking(); } // blocking filteredReduced() on sequences @@ -204,7 +204,7 @@ ResultType blockingFilteredReduced(const Sequence &sequence, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startFilteredReduced<ResultType>(sequence, QtPrivate::createFunctionWrapper(keep), QtPrivate::createFunctionWrapper(reduce), options) + return startFilteredReduced<ResultType>(sequence, keep, reduce, options) .startBlocking(); } @@ -217,8 +217,8 @@ ResultType blockingFilteredReduced(const Sequence &sequence, KeepFunctor keep, R | SequentialReduce)) { return startFilteredReduced<ResultType>( - sequence, QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + sequence, keep, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options) .startBlocking(); } @@ -230,11 +230,11 @@ typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingFiltered ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return blockingFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> + return startFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> (sequence, - QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), - options); + keep, + reduce, + options).startBlocking(); } template <typename Sequence, typename KeepFunctor, typename ReduceFunctor, @@ -246,10 +246,11 @@ ResultType blockingFilteredReduced(const Sequence &sequence, KeepFunctor keep, R ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return blockingFilteredReduced<ResultType>( - sequence, QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), - ResultType(std::forward<InitialValueType>(initialValue)), options); + return startFilteredReduced<ResultType>( + sequence, keep, + reduce, + ResultType(std::forward<InitialValueType>(initialValue)), options) + .startBlocking(); } #endif @@ -263,8 +264,8 @@ ResultType blockingFilteredReduced(Iterator begin, { return startFilteredReduced<ResultType> (begin, end, - QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + keep, + reduce, options) .startBlocking(); } @@ -278,8 +279,8 @@ ResultType blockingFilteredReduced(Iterator begin, Iterator end, KeepFunctor kee | SequentialReduce)) { return startFilteredReduced<ResultType>( - begin, end, QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + begin, end, keep, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options) .startBlocking(); } @@ -294,8 +295,8 @@ typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingFiltered { return startFilteredReduced<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> (begin, end, - QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + keep, + reduce, options) .startBlocking(); } @@ -310,8 +311,8 @@ ResultType blockingFilteredReduced(Iterator begin, Iterator end, KeepFunctor kee | SequentialReduce)) { return startFilteredReduced<ResultType>( - begin, end, QtPrivate::createFunctionWrapper(keep), - QtPrivate::createFunctionWrapper(reduce), + begin, end, keep, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options) .startBlocking(); } @@ -321,7 +322,7 @@ ResultType blockingFilteredReduced(Iterator begin, Iterator end, KeepFunctor kee template <typename Sequence, typename KeepFunctor> Sequence blockingFiltered(const Sequence &sequence, KeepFunctor keep) { - return startFilteredReduced<Sequence>(sequence, QtPrivate::createFunctionWrapper(keep), QtPrivate::PushBackWrapper(), OrderedReduce).startBlocking(); + return startFilteredReduced<Sequence>(sequence, keep, QtPrivate::PushBackWrapper(), OrderedReduce).startBlocking(); } // blocking filtered() on iterators @@ -329,7 +330,7 @@ template <typename OutputSequence, typename Iterator, typename KeepFunctor> OutputSequence blockingFiltered(Iterator begin, Iterator end, KeepFunctor keep) { return startFilteredReduced<OutputSequence>(begin, end, - QtPrivate::createFunctionWrapper(keep), + keep, QtPrivate::PushBackWrapper(), OrderedReduce).startBlocking(); } diff --git a/src/concurrent/qtconcurrentfilterkernel.h b/src/concurrent/qtconcurrentfilterkernel.h index 8ec551eeb2..babd173ff8 100644 --- a/src/concurrent/qtconcurrentfilterkernel.h +++ b/src/concurrent/qtconcurrentfilterkernel.h @@ -78,7 +78,7 @@ class FilterKernel : public IterateKernel<typename Sequence::const_iterator, voi { typedef ReduceKernel<ReduceFunctor, Sequence, typename Sequence::value_type> Reducer; typedef IterateKernel<typename Sequence::const_iterator, void> IterateKernelType; - typedef typename ReduceFunctor::result_type T; + typedef void T; Sequence reducedResult; Sequence &sequence; @@ -101,11 +101,11 @@ public: results.begin = index; results.end = index + 1; - if (keep(*it)) - results.vector.append(*it); + if (std::invoke(keep, *it)) + results.vector.append(*it); - reducer.runReduce(reduce, reducedResult, results); - return false; + reducer.runReduce(reduce, reducedResult, results); + return false; } bool runIterations(typename Sequence::const_iterator sequenceBeginIterator, int begin, int end, T *) override @@ -119,7 +119,7 @@ public: typename Sequence::const_iterator it = sequenceBeginIterator; std::advance(it, begin); for (int i = begin; i < end; ++i) { - if (keep(*it)) + if (std::invoke(keep, *it)) results.vector.append(*it); std::advance(it, 1); } @@ -189,7 +189,7 @@ public: results.begin = index; results.end = index + 1; - if (keep(*it)) + if (std::invoke(keep, *it)) results.vector.append(*it); reducer.runReduce(reduce, reducedResult, results); @@ -206,7 +206,7 @@ public: Iterator it = sequenceBeginIterator; std::advance(it, begin); for (int i = begin; i < end; ++i) { - if (keep(*it)) + if (std::invoke(keep, *it)) results.vector.append(*it); std::advance(it, 1); } @@ -264,7 +264,7 @@ public: bool runIteration(Iterator it, int index, T *) override { - if (keep(*it)) + if (std::invoke(keep, *it)) this->reportResult(&(*it), index); else this->reportResult(nullptr, index); @@ -282,7 +282,7 @@ public: Iterator it = sequenceBeginIterator; std::advance(it, begin); for (int i = begin; i < end; ++i) { - if (keep(*it)) + if (std::invoke(keep, *it)) results.vector.append(*it); std::advance(it, 1); } diff --git a/src/concurrent/qtconcurrentfunctionwrappers.h b/src/concurrent/qtconcurrentfunctionwrappers.h index 4731de77cc..34bbe89c86 100644 --- a/src/concurrent/qtconcurrentfunctionwrappers.h +++ b/src/concurrent/qtconcurrentfunctionwrappers.h @@ -43,165 +43,64 @@ #include <QtConcurrent/qtconcurrentcompilertest.h> #include <QtCore/QStringList> +#include <tuple> + #if !defined(QT_NO_CONCURRENT) || defined(Q_CLANG_QDOC) QT_BEGIN_NAMESPACE -namespace QtConcurrent { +namespace QtPrivate { -template <typename T, typename U> -class FunctionWrapper1 +struct PushBackWrapper { -public: - typedef T (*FunctionPointerType)(U u); - typedef T result_type; - inline FunctionWrapper1(FunctionPointerType _functionPointer) - :functionPointer(_functionPointer) { } - - inline T operator()(U u) + template <class C, class U> + inline void operator()(C &c, const U &u) const { - return functionPointer(u); + return c.push_back(u); } -private: - FunctionPointerType functionPointer; -}; - -template <typename T, typename C> -class MemberFunctionWrapper -{ -public: - typedef T (C::*FunctionPointerType)(); - typedef T result_type; - inline MemberFunctionWrapper(FunctionPointerType _functionPointer) - :functionPointer(_functionPointer) { } - - inline T operator()(C &c) + template <class C, class U> + inline void operator()(C &c, U &&u) const { - return (c.*functionPointer)(); + return c.push_back(u); } -private: - FunctionPointerType functionPointer; }; -template <typename T, typename C, typename U> -class MemberFunctionWrapper1 -{ -public: - typedef T (C::*FunctionPointerType)(U); - typedef T result_type; - - inline MemberFunctionWrapper1(FunctionPointerType _functionPointer) - : functionPointer(_functionPointer) - { } - - inline T operator()(C &c, U u) - { - return (c.*functionPointer)(u); - } - -private: - FunctionPointerType functionPointer; -}; +// -- MapResultType -template <typename T, typename C> -class ConstMemberFunctionWrapper +template <class T, class Enable = void> +struct Argument { -public: - typedef T (C::*FunctionPointerType)() const; - typedef T result_type; - inline ConstMemberFunctionWrapper(FunctionPointerType _functionPointer) - :functionPointer(_functionPointer) { } - - inline T operator()(const C &c) const - { - return (c.*functionPointer)(); - } -private: - FunctionPointerType functionPointer; + using Type = void; }; -} // namespace QtConcurrent. - -namespace QtPrivate { - -template <typename T> -const T& createFunctionWrapper(const T& t) +template <class Sequence> +struct Argument<Sequence, typename std::enable_if<IsIterableValue<Sequence>>::type> { - return t; -} - -template <typename T, typename U> -QtConcurrent::FunctionWrapper1<T, U> createFunctionWrapper(T (*func)(U)) -{ - return QtConcurrent::FunctionWrapper1<T, U>(func); -} - -template <typename T, typename C> -QtConcurrent::MemberFunctionWrapper<T, C> createFunctionWrapper(T (C::*func)()) -{ - return QtConcurrent::MemberFunctionWrapper<T, C>(func); -} - -template <typename T, typename C, typename U> -QtConcurrent::MemberFunctionWrapper1<T, C, U> createFunctionWrapper(T (C::*func)(U)) -{ - return QtConcurrent::MemberFunctionWrapper1<T, C, U>(func); -} - -template <typename T, typename C> -QtConcurrent::ConstMemberFunctionWrapper<T, C> createFunctionWrapper(T (C::*func)() const) -{ - return QtConcurrent::ConstMemberFunctionWrapper<T, C>(func); -} - -#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 -template <typename T, typename U> -QtConcurrent::FunctionWrapper1<T, U> createFunctionWrapper(T (*func)(U) noexcept) -{ - return QtConcurrent::FunctionWrapper1<T, U>(func); -} + using Type = std::decay_t<decltype(*std::begin(std::declval<Sequence>()))>; +}; -template <typename T, typename C> -QtConcurrent::MemberFunctionWrapper<T, C> createFunctionWrapper(T (C::*func)() noexcept) +template <class Iterator> +struct Argument<Iterator, typename std::enable_if<IsDereferenceableValue<Iterator>>::type> { - return QtConcurrent::MemberFunctionWrapper<T, C>(func); -} + using Type = std::decay_t<decltype(*std::declval<Iterator>())>; +}; -template <typename T, typename C, typename U> -QtConcurrent::MemberFunctionWrapper1<T, C, U> createFunctionWrapper(T (C::*func)(U) noexcept) -{ - return QtConcurrent::MemberFunctionWrapper1<T, C, U>(func); -} +template <class T> +using ArgumentType = typename Argument<T>::Type; -template <typename T, typename C> -QtConcurrent::ConstMemberFunctionWrapper<T, C> createFunctionWrapper(T (C::*func)() const noexcept) +template <class T, class MapFunctor> +struct MapResult { - return QtConcurrent::ConstMemberFunctionWrapper<T, C>(func); -} -#endif - -struct PushBackWrapper -{ - typedef void result_type; - - template <class C, class U> - inline void operator()(C &c, const U &u) const - { - return c.push_back(u); - } - - template <class C, class U> - inline void operator()(C &c, U &&u) const - { - return c.push_back(u); - } + static_assert(std::is_invocable_v<std::decay_t<MapFunctor>, ArgumentType<T>>, + "It's not possible to invoke the function with passed argument."); + using Type = std::invoke_result_t<std::decay_t<MapFunctor>, ArgumentType<T>>; }; -template <typename Functor, bool foo = HasResultType<Functor>::Value> -struct LazyResultType { typedef typename Functor::result_type Type; }; -template <typename Functor> -struct LazyResultType<Functor, false> { typedef void Type; }; +template <class T, class MapFunctor> +using MapResultType = typename MapResult<T, MapFunctor>::Type; + +// -- ReduceResultType template <class T> struct ReduceResultType; @@ -218,121 +117,52 @@ struct ReduceResultType<T(C::*)(U)> typedef C ResultType; }; -#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 -template <class U, class V> -struct ReduceResultType<void(*)(U&,V) noexcept> -{ - typedef U ResultType; -}; - -template <class T, class C, class U> -struct ReduceResultType<T(C::*)(U) noexcept> -{ - typedef C ResultType; -}; -#endif - -template <class InputSequence, class MapFunctor> -struct MapResultType -{ - typedef typename LazyResultType<MapFunctor>::Type ResultType; -}; - template <class U, class V> -struct MapResultType<void, U (*)(V)> +struct ReduceResultType<std::function<void(U&, V)>> { typedef U ResultType; }; -template <class T, class C> -struct MapResultType<void, T(C::*)() const> +template <typename R, typename ...A> +struct ReduceResultType<R(*)(A...)> { - typedef T ResultType; + using ResultType = typename std::tuple_element<0, std::tuple<A...>>::type; }; #if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 template <class U, class V> -struct MapResultType<void, U (*)(V) noexcept> +struct ReduceResultType<void(*)(U&,V) noexcept> { typedef U ResultType; }; -template <class T, class C> -struct MapResultType<void, T(C::*)() const noexcept> +template <class T, class C, class U> +struct ReduceResultType<T(C::*)(U) noexcept> { - typedef T ResultType; + typedef C ResultType; }; #endif -#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS - -template <template <typename> class InputSequence, typename MapFunctor, typename T> -struct MapResultType<InputSequence<T>, MapFunctor> -{ - typedef InputSequence<typename LazyResultType<MapFunctor>::Type> ResultType; -}; - -template <template <typename> class InputSequence, class T, class U, class V> -struct MapResultType<InputSequence<T>, U (*)(V)> -{ - typedef InputSequence<U> ResultType; -}; +// -- MapSequenceResultType -template <template <typename> class InputSequence, class T, class U, class C> -struct MapResultType<InputSequence<T>, U(C::*)() const> -{ - typedef InputSequence<U> ResultType; -}; - -#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 - -template <template <typename> class InputSequence, class T, class U, class V> -struct MapResultType<InputSequence<T>, U (*)(V) noexcept> -{ - typedef InputSequence<U> ResultType; -}; - -template <template <typename> class InputSequence, class T, class U, class C> -struct MapResultType<InputSequence<T>, U(C::*)() const noexcept> -{ - typedef InputSequence<U> ResultType; -}; -#endif - -#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER +template <class InputSequence, class MapFunctor> +struct MapSequenceResultType; template <class MapFunctor> -struct MapResultType<QStringList, MapFunctor> +struct MapSequenceResultType<QStringList, MapFunctor> { - typedef QList<typename LazyResultType<MapFunctor>::Type> ResultType; + typedef QList<QtPrivate::MapResultType<QStringList, MapFunctor>> ResultType; }; -template <class U, class V> -struct MapResultType<QStringList, U (*)(V)> -{ - typedef QList<U> ResultType; -}; - -template <class U, class C> -struct MapResultType<QStringList, U(C::*)() const> -{ - typedef QList<U> ResultType; -}; - -#if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 +#ifndef QT_NO_TEMPLATE_TEMPLATE_PARAMETERS -template <class U, class V> -struct MapResultType<QStringList, U (*)(V) noexcept> +template <template <typename> class InputSequence, typename MapFunctor, typename T> +struct MapSequenceResultType<InputSequence<T>, MapFunctor> { - typedef QList<U> ResultType; + typedef InputSequence<QtPrivate::MapResultType<InputSequence<T>, MapFunctor>> ResultType; }; -template <class U, class C> -struct MapResultType<QStringList, U(C::*)() const noexcept> -{ - typedef QList<U> ResultType; -}; -#endif +#endif // QT_NO_TEMPLATE_TEMPLATE_PARAMETER } // namespace QtPrivate. diff --git a/src/concurrent/qtconcurrentmap.cpp b/src/concurrent/qtconcurrentmap.cpp index 92fe7a98f2..2ad5483540 100644 --- a/src/concurrent/qtconcurrentmap.cpp +++ b/src/concurrent/qtconcurrentmap.cpp @@ -270,8 +270,7 @@ QtConcurrent::map(), QtConcurrent::mapped(), and QtConcurrent::mappedReduced() accept function objects for the map function. These function objects can be used to - add state to a function call. The result_type typedef must define the - result type of the function call operator: + add state to a function call: \snippet code/src_concurrent_qtconcurrentmap.cpp 14 @@ -281,6 +280,26 @@ \snippet code/src_concurrent_qtconcurrentmap.cpp 11 + \section2 Using Lambda Expressions + + QtConcurrent::map(), QtConcurrent::mapped(), and + QtConcurrent::mappedReduced() accept lambda expressions for the map and + reduce function: + + \snippet code/src_concurrent_qtconcurrentmap.cpp 15 + + When using QtConcurrent::mappedReduced() or + QtConcurrent::blockingMappedReduced(), you can mix the use of normal + functions, member functions and lambda expressions freely. + + \snippet code/src_concurrent_qtconcurrentmap.cpp 16 + + For the reduce function, lambda expressions are not directly supported. + Lambda expressions can, however, be used when the type of the reduction + result is explicitly specified: + + \snippet code/src_concurrent_qtconcurrentmap.cpp 17 + \section2 Wrapping Functions that Take Multiple Arguments If you want to use a map function that takes more than one argument you can @@ -321,7 +340,7 @@ */ /*! - \fn template <typename Sequence, typename MapFunctor> QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> QtConcurrent::mapped(const Sequence &sequence, MapFunctor function) + \fn template <typename Sequence, typename MapFunctor> QFuture<QtPrivate::MapResultType<Sequence, MapFunctor>> QtConcurrent::mapped(const Sequence &sequence, MapFunctor function) Calls \a function once for each item in \a sequence and returns a future with each mapped item as a result. You can use QFuture::const_iterator or @@ -331,7 +350,7 @@ */ /*! - \fn template <typename Iterator, typename MapFunctor> QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> QtConcurrent::mapped(Iterator begin, Iterator end, MapFunctor function) + \fn template <typename Iterator, typename MapFunctor> QFuture<QtPrivate::MapResultType<Iterator, MapFunctor>> QtConcurrent::mapped(Iterator begin, Iterator end, MapFunctor function) Calls \a function once for each item from \a begin to \a end and returns a future with each mapped item as a result. You can use @@ -522,27 +541,3 @@ \sa blockingMappedReduced(), {Concurrent Map and Map-Reduce} */ - -/*! - \class QtConcurrent::FunctionWrapper1 - \inmodule QtConcurrent - \internal -*/ - -/*! - \class QtConcurrent::MemberFunctionWrapper - \inmodule QtConcurrent - \internal -*/ - -/*! - \class QtConcurrent::MemberFunctionWrapper1 - \inmodule QtConcurrent - \internal -*/ - -/*! - \class QtConcurrent::ConstMemberFunctionWrapper - \inmodule QtConcurrent - \internal -*/ diff --git a/src/concurrent/qtconcurrentmap.h b/src/concurrent/qtconcurrentmap.h index a1e7cf1044..9b8ccc3eaf 100644 --- a/src/concurrent/qtconcurrentmap.h +++ b/src/concurrent/qtconcurrentmap.h @@ -59,14 +59,14 @@ namespace QtConcurrent { template <typename Sequence, typename MapFunctor> QFuture<void> map(Sequence &sequence, MapFunctor map) { - return startMap(sequence.begin(), sequence.end(), QtPrivate::createFunctionWrapper(map)); + return startMap(sequence.begin(), sequence.end(), map); } // map() on iterators template <typename Iterator, typename MapFunctor> QFuture<void> map(Iterator begin, Iterator end, MapFunctor map) { - return startMap(begin, end, QtPrivate::createFunctionWrapper(map)); + return startMap(begin, end, map); } // mappedReduced() for sequences. @@ -76,10 +76,10 @@ QFuture<ResultType> mappedReduced(const Sequence &sequence, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType> + return startMappedReduced<QtPrivate::MapResultType<Sequence, MapFunctor>, ResultType> (sequence, - QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + map, + reduce, options); } @@ -91,9 +91,9 @@ QFuture<ResultType> mappedReduced(const Sequence &sequence, MapFunctor map, Redu ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, - ResultType>(sequence, QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + return startMappedReduced<QtPrivate::MapResultType<Sequence, MapFunctor>, + ResultType>(sequence, map, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options); } @@ -104,10 +104,11 @@ QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedR ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> + return startMappedReduced<QtPrivate::MapResultType<Sequence, MapFunctor>, + typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> (sequence, - QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + map, + reduce, options); } @@ -120,10 +121,10 @@ QFuture<ResultType> mappedReduced(const Sequence &sequence, MapFunctor map, Redu ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, + return startMappedReduced<QtPrivate::MapResultType<Sequence, MapFunctor>, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>( - sequence, QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + sequence, map, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options); } @@ -135,10 +136,10 @@ QFuture<ResultType> mappedReduced(Iterator begin, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType> + return startMappedReduced<QtPrivate::MapResultType<Iterator, MapFunctor>, ResultType> (begin, end, - QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + map, + reduce, options); } @@ -150,9 +151,9 @@ QFuture<ResultType> mappedReduced(Iterator begin, Iterator end, MapFunctor map, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, - ResultType>(begin, end, QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + return startMappedReduced<QtPrivate::MapResultType<Iterator, MapFunctor>, + ResultType>(begin, end, map, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options); } @@ -164,10 +165,11 @@ QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedR ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> + return startMappedReduced<QtPrivate::MapResultType<Iterator, MapFunctor>, + typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> (begin, end, - QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + map, + reduce, options); } @@ -180,39 +182,39 @@ QFuture<typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> mappedR InitialValueType &&initialValue, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, + return startMappedReduced<QtPrivate::MapResultType<Iterator, MapFunctor>, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>( - begin, end, QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + begin, end, map, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options); } // mapped() for sequences template <typename Sequence, typename MapFunctor> -QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> mapped(const Sequence &sequence, MapFunctor map) +QFuture<QtPrivate::MapResultType<Sequence, MapFunctor>> mapped(const Sequence &sequence, MapFunctor map) { - return startMapped<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType>(sequence, QtPrivate::createFunctionWrapper(map)); + return startMapped<QtPrivate::MapResultType<Sequence, MapFunctor>>(sequence, map); } // mapped() for iterator ranges. template <typename Iterator, typename MapFunctor> -QFuture<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType> mapped(Iterator begin, Iterator end, MapFunctor map) +QFuture<QtPrivate::MapResultType<Iterator, MapFunctor>> mapped(Iterator begin, Iterator end, MapFunctor map) { - return startMapped<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType>(begin, end, QtPrivate::createFunctionWrapper(map)); + return startMapped<QtPrivate::MapResultType<Iterator, MapFunctor>>(begin, end, map); } // blockingMap() for sequences template <typename Sequence, typename MapFunctor> void blockingMap(Sequence &sequence, MapFunctor map) { - startMap(sequence.begin(), sequence.end(), QtPrivate::createFunctionWrapper(map)).startBlocking(); + startMap(sequence.begin(), sequence.end(), map).startBlocking(); } // blockingMap() for iterator ranges template <typename Iterator, typename MapFunctor> void blockingMap(Iterator begin, Iterator end, MapFunctor map) { - startMap(begin, end, QtPrivate::createFunctionWrapper(map)).startBlocking(); + startMap(begin, end, map).startBlocking(); } // blockingMappedReduced() for sequences @@ -222,10 +224,10 @@ ResultType blockingMappedReduced(const Sequence &sequence, ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType> + return QtConcurrent::startMappedReduced<QtPrivate::MapResultType<Sequence, MapFunctor>, ResultType> (sequence, - QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + map, + reduce, options) .startBlocking(); } @@ -239,9 +241,9 @@ ResultType blockingMappedReduced(const Sequence &sequence, MapFunctor map, Reduc | SequentialReduce)) { return QtConcurrent::startMappedReduced< - typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>( - sequence, QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + QtPrivate::MapResultType<Sequence, MapFunctor>, ResultType>( + sequence, map, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options) .startBlocking(); } @@ -252,10 +254,11 @@ typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedRe ReduceFunctor reduce, ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { - return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> + return QtConcurrent::startMappedReduced<QtPrivate::MapResultType<Sequence, MapFunctor>, + typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> (sequence, - QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + map, + reduce, options) .startBlocking(); } @@ -270,10 +273,10 @@ typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedRe ReduceOptions options = ReduceOptions(UnorderedReduce | SequentialReduce)) { return QtConcurrent::startMappedReduced< - typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, + QtPrivate::MapResultType<Sequence, MapFunctor>, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>( - sequence, QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + sequence, map, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options) .startBlocking(); } @@ -286,10 +289,10 @@ ResultType blockingMappedReduced(Iterator begin, ReduceFunctor reduce, QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce)) { - return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType> + return QtConcurrent::startMappedReduced<QtPrivate::MapResultType<Iterator, MapFunctor>, ResultType> (begin, end, - QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + map, + reduce, options) .startBlocking(); } @@ -304,9 +307,9 @@ ResultType blockingMappedReduced(Iterator begin, Iterator end, MapFunctor map, R | QtConcurrent::SequentialReduce)) { return QtConcurrent::startMappedReduced< - typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, ResultType>( - begin, end, QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + QtPrivate::MapResultType<Iterator, MapFunctor>, ResultType>( + begin, end, map, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options) .startBlocking(); } @@ -318,10 +321,11 @@ typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedRe ReduceFunctor reduce, QtConcurrent::ReduceOptions options = QtConcurrent::ReduceOptions(QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce)) { - return QtConcurrent::startMappedReduced<typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> + return QtConcurrent::startMappedReduced<QtPrivate::MapResultType<Iterator, MapFunctor>, + typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType> (begin, end, - QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + map, + reduce, options) .startBlocking(); } @@ -337,10 +341,10 @@ typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType blockingMappedRe QtConcurrent::UnorderedReduce | QtConcurrent::SequentialReduce)) { return QtConcurrent::startMappedReduced< - typename QtPrivate::MapResultType<void, MapFunctor>::ResultType, + QtPrivate::MapResultType<Iterator, MapFunctor>, typename QtPrivate::ReduceResultType<ReduceFunctor>::ResultType>( - begin, end, QtPrivate::createFunctionWrapper(map), - QtPrivate::createFunctionWrapper(reduce), + begin, end, map, + reduce, ResultType(std::forward<InitialValueType>(initialValue)), options) .startBlocking(); } @@ -351,18 +355,18 @@ OutputSequence blockingMapped(const InputSequence &sequence, MapFunctor map) { return blockingMappedReduced<OutputSequence> (sequence, - QtPrivate::createFunctionWrapper(map), + map, QtPrivate::PushBackWrapper(), QtConcurrent::OrderedReduce); } template <typename MapFunctor, typename InputSequence> -typename QtPrivate::MapResultType<InputSequence, MapFunctor>::ResultType blockingMapped(const InputSequence &sequence, MapFunctor map) +auto blockingMapped(const InputSequence &sequence, MapFunctor map) { - typedef typename QtPrivate::MapResultType<InputSequence, MapFunctor>::ResultType OutputSequence; + using OutputSequence = typename QtPrivate::MapSequenceResultType<InputSequence, MapFunctor>::ResultType; return blockingMappedReduced<OutputSequence> (sequence, - QtPrivate::createFunctionWrapper(map), + map, QtPrivate::PushBackWrapper(), QtConcurrent::OrderedReduce); } @@ -373,18 +377,18 @@ Sequence blockingMapped(Iterator begin, Iterator end, MapFunctor map) { return blockingMappedReduced<Sequence> (begin, end, - QtPrivate::createFunctionWrapper(map), + map, QtPrivate::PushBackWrapper(), QtConcurrent::OrderedReduce); } template <typename Iterator, typename MapFunctor> -typename QtPrivate::MapResultType<Iterator, MapFunctor>::ResultType blockingMapped(Iterator begin, Iterator end, MapFunctor map) +auto blockingMapped(Iterator begin, Iterator end, MapFunctor map) { - typedef typename QtPrivate::MapResultType<Iterator, MapFunctor>::ResultType OutputSequence; + using OutputSequence = QtPrivate::MapResultType<Iterator, MapFunctor>; return blockingMappedReduced<OutputSequence> (begin, end, - QtPrivate::createFunctionWrapper(map), + map, QtPrivate::PushBackWrapper(), QtConcurrent::OrderedReduce); } diff --git a/src/concurrent/qtconcurrentmapkernel.h b/src/concurrent/qtconcurrentmapkernel.h index 3de275a192..346ffbfc7f 100644 --- a/src/concurrent/qtconcurrentmapkernel.h +++ b/src/concurrent/qtconcurrentmapkernel.h @@ -46,6 +46,7 @@ #include <QtConcurrent/qtconcurrentiteratekernel.h> #include <QtConcurrent/qtconcurrentreducekernel.h> +#include <QtConcurrent/qtconcurrentfunctionwrappers.h> QT_BEGIN_NAMESPACE @@ -65,7 +66,7 @@ public: bool runIteration(Iterator it, int, void *) override { - map(*it); + std::invoke(map, *it); return false; } @@ -88,13 +89,15 @@ template <typename ReducedResultType, typename ReduceFunctor, typename Reducer = ReduceKernel<ReduceFunctor, ReducedResultType, - typename MapFunctor::result_type> > + QtPrivate::MapResultType<Iterator, MapFunctor>>> class MappedReducedKernel : public IterateKernel<Iterator, ReducedResultType> { ReducedResultType reducedResult; MapFunctor map; ReduceFunctor reduce; Reducer reducer; + using IntermediateResultsType = QtPrivate::MapResultType<Iterator, MapFunctor>; + public: typedef ReducedResultType ReturnType; MappedReducedKernel(Iterator begin, Iterator end, MapFunctor _map, ReduceFunctor _reduce, ReduceOptions reduceOptions) @@ -113,18 +116,18 @@ public: bool runIteration(Iterator it, int index, ReducedResultType *) override { - IntermediateResults<typename MapFunctor::result_type> results; + IntermediateResults<IntermediateResultsType> results; results.begin = index; results.end = index + 1; - results.vector.append(map(*it)); + results.vector.append(std::invoke(map, *it)); reducer.runReduce(reduce, reducedResult, results); return false; } bool runIterations(Iterator sequenceBeginIterator, int beginIndex, int endIndex, ReducedResultType *) override { - IntermediateResults<typename MapFunctor::result_type> results; + IntermediateResults<IntermediateResultsType> results; results.begin = beginIndex; results.end = endIndex; results.vector.reserve(endIndex - beginIndex); @@ -132,7 +135,7 @@ public: Iterator it = sequenceBeginIterator; std::advance(it, beginIndex); for (int i = beginIndex; i < endIndex; ++i) { - results.vector.append(map(*(it))); + results.vector.append(std::invoke(map, *it)); std::advance(it, 1); } @@ -163,20 +166,18 @@ public: }; template <typename Iterator, typename MapFunctor> -class MappedEachKernel : public IterateKernel<Iterator, typename MapFunctor::result_type> +class MappedEachKernel : public IterateKernel<Iterator, QtPrivate::MapResultType<Iterator, MapFunctor>> { MapFunctor map; - typedef typename MapFunctor::result_type T; -public: - typedef T ReturnType; - typedef T ResultType; + using T = QtPrivate::MapResultType<Iterator, MapFunctor>; +public: MappedEachKernel(Iterator begin, Iterator end, MapFunctor _map) : IterateKernel<Iterator, T>(begin, end), map(_map) { } bool runIteration(Iterator it, int, T *result) override { - *result = map(*it); + *result = std::invoke(map, *it); return true; } diff --git a/src/concurrent/qtconcurrentreducekernel.h b/src/concurrent/qtconcurrentreducekernel.h index eabc432374..a487ec26a2 100644 --- a/src/concurrent/qtconcurrentreducekernel.h +++ b/src/concurrent/qtconcurrentreducekernel.h @@ -124,7 +124,7 @@ class ReduceKernel const IntermediateResults<T> &result) { for (int i = 0; i < result.vector.size(); ++i) { - reduce(r, result.vector.at(i)); + std::invoke(reduce, r, result.vector.at(i)); } } diff --git a/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp b/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp index 1b52f52038..e89e5cf2e3 100644 --- a/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp +++ b/tests/auto/concurrent/qtconcurrentfilter/tst_qtconcurrentfilter.cpp @@ -38,12 +38,16 @@ class tst_QtConcurrentFilter : public QObject private slots: void filter(); + void filterLambda(); void filtered(); + void filteredLambda(); void filteredReduced(); + void filteredReduceLambda(); void resultAt(); void incrementalResults(); void noDetach(); void stlContainers(); + void stlContainersLambda(); void filteredReduceInitialValue(); }; @@ -118,6 +122,22 @@ void tst_QtConcurrentFilter::filter() } } +void tst_QtConcurrentFilter::filterLambda() +{ + { + QList<Number> list; + list << 1 << 2 << 3 << 4; + QtConcurrent::filter(list, [](const Number &number) { return number.isEven(); }).waitForFinished(); + QCOMPARE(list, QList<Number>() << 2 << 4); + } + { + QList<Number> list; + list << 1 << 2 << 3 << 4; + QtConcurrent::blockingFilter(list, [](const Number &number) { return number.isEven(); }); + QCOMPARE(list, QList<Number>() << 2 << 4); + } +} + void tst_QtConcurrentFilter::filtered() { QList<int> list; @@ -292,6 +312,64 @@ void tst_QtConcurrentFilter::filtered() } } +void tst_QtConcurrentFilter::filteredLambda() +{ + QList<int> list; + list << 1 << 2 << 3 << 4; + + { + QFuture<int> f = QtConcurrent::filtered(list, + [](int x) { + return (x & 1) == 0; + } + ); + QList<int> list2 = f.results(); + QCOMPARE(list2, QList<int>() << 2 << 4); + } + { + QFuture<int> f = QtConcurrent::filtered(list.begin(), list.end(), + [](const int &x) { + return (x & 1) == 0; + } + ); + QList<int> list2 = f.results(); + QCOMPARE(list2, QList<int>() << 2 << 4); + } + { + QFuture<int> f = QtConcurrent::filtered(list.constBegin(), list.constEnd(), + [](const int &x) { + return (x & 1) == 0; + } + ); + QList<int> list2 = f.results(); + QCOMPARE(list2, QList<int>() << 2 << 4); + } + { + QList<int> list2 = QtConcurrent::blockingFiltered(list, + [](const int &x) { + return (x & 1) == 0; + } + ); + QCOMPARE(list2, QList<int>() << 2 << 4); + } + { + QList<int> list2 = QtConcurrent::blockingFiltered<QList<int> >(list.begin(), list.end(), + [](const int &x) { + return (x & 1) == 0; + } + ); + QCOMPARE(list2, QList<int>() << 2 << 4); + } + { + QList<int> list2 = QtConcurrent::blockingFiltered<QList<int> >(list.constBegin(), list.constEnd(), + [](const int &x) { + return (x & 1) == 0; + } + ); + QCOMPARE(list2, QList<int>() << 2 << 4); + } +} + void tst_QtConcurrentFilter::filteredReduced() { QList<int> list; @@ -728,7 +806,221 @@ void tst_QtConcurrentFilter::filteredReduced() numberSumReduce); QCOMPARE(sum, 6); } +} + +void tst_QtConcurrentFilter::filteredReduceLambda() +{ + QList<int> list; + list << 1 << 2 << 3 << 4; + QList<Number> numberList; + numberList << 1 << 2 << 3 << 4; + + // lambda-lambda + { + int sum = QtConcurrent::filteredReduced<int>(list, + [](const int &x) { + return (x & 1) == 0; + }, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced<int>(list, + [](const int &x) { + return (x & 1) == 0; + }, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 6); + } + // lambda-functor + { + int sum = QtConcurrent::filteredReduced<int>(list, + [](const int &x) { + return (x & 1) == 0; + }, + IntSumReduce() + ); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced<int>(list, + [](const int &x) { + return (x & 1) == 0; + }, + IntSumReduce() + ); + QCOMPARE(sum2, 6); + } + + // functor-lambda + { + int sum = QtConcurrent::filteredReduced<int>(list, + KeepEvenIntegers(), + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::blockingFilteredReduced<int>(list, + KeepEvenIntegers(), + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 6); + } + + // lambda-function + { + int sum = QtConcurrent::filteredReduced(list, + [] (const int &x) { + return (x & 1) == 0; + }, + intSumReduce + ); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced(list.begin(), list.end(), + [](const int &x) { + return (x & 1) == 0; + }, + intSumReduce + ); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::blockingFilteredReduced(list, + [] (const int &x) { + return (x & 1) == 0; + }, + intSumReduce + ); + QCOMPARE(sum3, 6); + + int sum4 = QtConcurrent::blockingFilteredReduced(list.begin(), list.end(), + [] (const int &x) { + return (x & 1) == 0; + }, + intSumReduce + ); + QCOMPARE(sum4, 6); + } + + // function-lambda + { + int sum = QtConcurrent::filteredReduced<int>(list, + keepEvenIntegers, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced<int>(list.begin(), list.end(), + keepEvenIntegers, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::blockingFilteredReduced<int>(list, + keepEvenIntegers, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum3, 6); + + int sum4 = QtConcurrent::blockingFilteredReduced<int>(list.begin(), list.end(), + keepEvenIntegers, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum4, 6); + } + + // lambda-member + { + auto push_back = static_cast<void (QVector<int>::*)(const int &)>(&QVector<int>::push_back); + + QList<int> list2 = QtConcurrent::filteredReduced(list, + [] (const int &x) { + return (x & 1) == 0; + }, + push_back, + QtConcurrent::OrderedReduce + ); + QCOMPARE(list2, QList<int>() << 2 << 4); + + QList<int> list3 = QtConcurrent::filteredReduced(list.begin(), list.end(), + [] (const int &x) { + return (x & 1) == 0; + }, + push_back, + QtConcurrent::OrderedReduce + ); + QCOMPARE(list3, QList<int>() << 2 << 4); + + QList<int> list4 = QtConcurrent::blockingFilteredReduced(list, + [] (const int &x) { + return (x & 1) == 0; + }, + push_back, + QtConcurrent::OrderedReduce + ); + QCOMPARE(list4, QList<int>() << 2 << 4); + + QList<int> list5 = QtConcurrent::blockingFilteredReduced(list.begin(), list.end(), + [] (const int &x) { + return (x & 1) == 0; + }, + push_back, + QtConcurrent::OrderedReduce + ); + QCOMPARE(list5, QList<int>() << 2 << 4); + } + + // member-lambda + { + int sum = QtConcurrent::filteredReduced<int>(numberList, + &Number::isEven, + [](int &sum, const Number &x) { + sum += x.toInt(); + } + ); + QCOMPARE(sum, 6); + + int sum2 = QtConcurrent::filteredReduced<int>(numberList.begin(), numberList.end(), + &Number::isEven, + [](int &sum, const Number &x) { + sum += x.toInt(); + } + ); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::blockingFilteredReduced<int>(numberList, + &Number::isEven, + [](int &sum, const Number &x) { + sum += x.toInt(); + } + ); + QCOMPARE(sum3, 6); + + int sum4 = QtConcurrent::blockingFilteredReduced<int>(numberList.begin(), numberList.end(), + &Number::isEven, + [](int &sum, const Number &x) { + sum += x.toInt(); + } + ); + QCOMPARE(sum4, 6); + } } bool filterfn(int i) @@ -857,6 +1149,57 @@ void tst_QtConcurrentFilter::stlContainers() QCOMPARE(*list2.begin(), 1); } +void tst_QtConcurrentFilter::stlContainersLambda() +{ + std::vector<int> vector; + vector.push_back(1); + vector.push_back(2); + + std::vector<int> vector2 = QtConcurrent::blockingFiltered(vector, + [](const int &i) { + return waitFilterfn(i); + } + ); + QCOMPARE(vector2.size(), (std::vector<int>::size_type)(1)); + QCOMPARE(vector2[0], 1); + + std::list<int> list; + list.push_back(1); + list.push_back(2); + + std::list<int> list2 = QtConcurrent::blockingFiltered(list, + [](const int &i) { + return waitFilterfn(i); + } + ); + QCOMPARE(list2.size(), (std::list<int>::size_type)(1)); + QCOMPARE(*list2.begin(), 1); + + QtConcurrent::filtered(list, + [](const int &i) { + return waitFilterfn(i); + } + ).waitForFinished(); + QtConcurrent::filtered(vector, + [](const int &i) { + return waitFilterfn(i); + } + ).waitForFinished(); + QtConcurrent::filtered(vector.begin(), vector.end(), + [](const int &i) { + return waitFilterfn(i); + } + ).waitForFinished(); + + QtConcurrent::blockingFilter(list, + [](const int &i) { + return waitFilterfn(i); + } + ); + QCOMPARE(list.size(), (std::list<int>::size_type)(1)); + QCOMPARE(*list.begin(), 1); +} + void tst_QtConcurrentFilter::filteredReduceInitialValue() { // This test's the same as filteredReduce, but with an initial value on all calls diff --git a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp index 1a8978c7ea..85acc6f729 100644 --- a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp +++ b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp @@ -36,7 +36,7 @@ #include "functions.h" -class tst_QtConcurrentMap: public QObject +class tst_QtConcurrentMap : public QObject { Q_OBJECT private slots: @@ -45,7 +45,9 @@ private slots: void mapped(); void blocking_mapped(); void mappedReduced(); + void mappedReducedLambda(); void blocking_mappedReduced(); + void blocking_mappedReducedLambda(); void assignResult(); void functionOverloads(); void noExceptFunctionOverloads(); @@ -55,6 +57,7 @@ private slots: void incrementalResults(); void noDetach(); void stlContainers(); + void stlContainersLambda(); void qFutureAssignmentLeak(); void stressTest(); void persistentResultTest(); @@ -240,6 +243,12 @@ void tst_QtConcurrentMap::blocking_map() QCOMPARE(numberList, QList<Number>() << 2 << 4 << 6); QtConcurrent::blockingMap(numberList.begin(), numberList.end(), &Number::multiplyBy2); QCOMPARE(numberList, QList<Number>() << 4 << 8 << 12); + + // lambda + QtConcurrent::blockingMap(list, [](int &x) { x *= 2; }); + QCOMPARE(list, QList<int>() << 128 << 256 << 384); + QtConcurrent::blockingMap(list.begin(), list.end(), [](int &x) { x *= 2; }); + QCOMPARE(list, QList<int>() << 256 << 512 << 768); } // functors don't take arguments by reference, making these no-ops @@ -264,6 +273,12 @@ void tst_QtConcurrentMap::blocking_map() QCOMPARE(list, QList<int>() << 1 << 2 << 3); QtConcurrent::blockingMap(list.begin(), list.end(), multiplyBy2Immutable); QCOMPARE(list, QList<int>() << 1 << 2 << 3); + + // lambda + QtConcurrent::blockingMap(list, [](int x) { x *= 2; }); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QtConcurrent::blockingMap(list.begin(), list.end(), [](int x) { x *= 2; }); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); } #if 0 @@ -317,8 +332,6 @@ int multiplyBy2(int x) class MultiplyBy2 { public: - typedef int result_type; - int operator()(int x) const { int y = x * 2; @@ -334,8 +347,6 @@ double intToDouble(int x) class IntToDouble { public: - typedef double result_type; - double operator()(int x) const { return double(x); @@ -350,8 +361,6 @@ int stringToInt(const QString &string) class StringToInt { public: - typedef int result_type; - int operator()(const QString &string) const { return string.toInt(); @@ -437,6 +446,32 @@ void tst_QtConcurrentMap::mapped() QCOMPARE(numberList4, QList<Number>() << 2 << 4 << 6); } + { + QList<Number> numberList2 = QtConcurrent::mapped(numberList, + [](const Number &num) { + return num.multipliedBy2(); + } + ).results(); + QCOMPARE(numberList, QList<Number>() << 1 << 2 << 3); + QCOMPARE(numberList2, QList<Number>() << 2 << 4 << 6); + + QList<Number> numberList3 = QtConcurrent::mapped(numberList.constBegin(), numberList.constEnd(), + [](const Number &num) { + return num.multipliedBy2(); + } + ).results(); + QCOMPARE(numberList, QList<Number>() << 1 << 2 << 3); + QCOMPARE(numberList3, QList<Number>() << 2 << 4 << 6); + + QList<Number> numberList4 = QtConcurrent::mapped(QList<Number>(numberList), + [](const Number &num) { + return num.multipliedBy2(); + } + ).results(); + QCOMPARE(numberList, QList<Number>() << 1 << 2 << 3); + QCOMPARE(numberList4, QList<Number>() << 2 << 4 << 6); + } + // change the value_type, same container // functor @@ -517,6 +552,33 @@ void tst_QtConcurrentMap::mapped() QCOMPARE(list4, QList<QString>() << "1" << "2" << "3"); } + // lambda + { + QList<double> list2 = QtConcurrent::mapped(list, + [](int x) { + return double(x); + } + ).results(); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list2, QList<double>() << 1.0 << 2.0 << 3.0); + + QList<double> list3 = QtConcurrent::mapped(list.constBegin(), list.constEnd(), + [](int x) { + return double(x); + } + ).results(); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list3, QList<double>() << 1.0 << 2.0 << 3.0); + + QList<double> list4 = QtConcurrent::mapped(QList<int>(list), + [](int x) { + return double(x); + } + ).results(); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list4, QList<double>() << 1.0 << 2.0 << 3.0); + } + // change the value_type { QList<QString> strings = QStringList() << "1" << "2" << "3"; @@ -551,6 +613,22 @@ void tst_QtConcurrentMap::mapped() QCOMPARE(numberList3, QList<int>() << 1 << 2 << 3); } + { + QList<int> numberList2 = QtConcurrent::mapped(numberList, + [] (const Number number) { + return number.toInt(); + } + ).results(); + QCOMPARE(numberList2, QList<int>() << 1 << 2 << 3); + + QList<int> numberList3 = QtConcurrent::mapped(numberList.constBegin(), numberList.constEnd(), + [](const Number number) { + return number.toInt(); + } + ).results(); + QCOMPARE(numberList3, QList<int>() << 1 << 2 << 3); + } + // change the value_type from QStringList { QStringList strings = QStringList() << "1" << "2" << "3"; @@ -574,6 +652,22 @@ void tst_QtConcurrentMap::mapped() .results(); QCOMPARE(list2, QList<int>() << 1 << 2 << 3); } + { + QStringList strings = QStringList() << "1" << "2" << "3"; + QList<int> list = QtConcurrent::mapped(strings, + [](const QString &string) { + return string.toInt(); + } + ).results(); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + + QList<int> list2 = QtConcurrent::mapped(strings.constBegin(), strings.constEnd(), + [](const QString &string) { + return string.toInt(); + } + ).results(); + QCOMPARE(list2, QList<int>() << 1 << 2 << 3); + } } void tst_QtConcurrentMap::blocking_mapped() @@ -652,6 +746,33 @@ void tst_QtConcurrentMap::blocking_mapped() QCOMPARE(numberList4, QList<Number>() << 2 << 4 << 6); } + // lambda + { + QList<int> list2 = QtConcurrent::blockingMapped(list, + [](int x) { + return x * 2; + } + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list2, QList<int>() << 2 << 4 << 6); + + QList<int> list3 = QtConcurrent::blockingMapped<QList<int> >(list.constBegin(), list.constEnd(), + [](int x) { + return x * 2; + } + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list3, QList<int>() << 2 << 4 << 6); + + QList<int> list4 = QtConcurrent::blockingMapped(QList<int>(list), + [](int x) { + return x * 2; + } + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list4, QList<int>() << 2 << 4 << 6); + } + // change the value_type, same container // functor @@ -727,6 +848,34 @@ void tst_QtConcurrentMap::blocking_mapped() QCOMPARE(list4, QList<QString>() << "1" << "2" << "3"); } + // lambda + { + QList<QString> list2 = QtConcurrent::blockingMapped<QList<QString> >(numberList, + [] (const Number &number) { + return number.toString(); + } + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list2, QList<QString>() << "1" << "2" << "3"); + + QList<QString> list3 = QtConcurrent::blockingMapped<QList<QString> >(numberList.constBegin(), + numberList.constEnd(), + [](const Number &number) { + return number.toString(); + } + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list3, QList<QString>() << "1" << "2" << "3"); + + QList<QString> list4 = QtConcurrent::blockingMapped<QList<QString> >(QList<Number>(numberList), + [](const Number &number) { + return number.toString(); + } + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list4, QList<QString>() << "1" << "2" << "3"); + } + // change the value_type { QList<QString> strings = QStringList() << "1" << "2" << "3"; @@ -759,6 +908,23 @@ void tst_QtConcurrentMap::blocking_mapped() QCOMPARE(numberList3, QList<int>() << 1 << 2 << 3); } + { + QList<int> numberList2 = QtConcurrent::blockingMapped(numberList, + [] (const Number &number) { + return number.toInt(); + } + ); + QCOMPARE(numberList2, QList<int>() << 1 << 2 << 3); + + QList<int> numberList3 = QtConcurrent::blockingMapped<QList<int> >(numberList.constBegin(), + numberList.constEnd(), + [](const Number &number) { + return number.toInt(); + } + ); + QCOMPARE(numberList3, QList<int>() << 1 << 2 << 3); + } + // change the value_type from QStringList { QStringList strings = QStringList() << "1" << "2" << "3"; @@ -780,6 +946,23 @@ void tst_QtConcurrentMap::blocking_mapped() stringToInt); QCOMPARE(list2, QList<int>() << 1 << 2 << 3); } + { + QStringList strings = QStringList() << "1" << "2" << "3"; + QList<int> list = QtConcurrent::blockingMapped(strings, + [](const QString &string) { + return string.toInt(); + } + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + + QList<int> list2 = QtConcurrent::blockingMapped<QList<int> >(strings.constBegin(), + strings.constEnd(), + [](const QString &string) { + return string.toInt(); + } + ); + QCOMPARE(list2, QList<int>() << 1 << 2 << 3); + } // functor { @@ -882,6 +1065,40 @@ void tst_QtConcurrentMap::blocking_mapped() QCOMPARE(list5, QVector<int>() << 1 << 2 << 3); #endif } + + // lambda + { + QVector<double> list2 = QtConcurrent::blockingMapped<QVector<double> >(list, + [](int x) { + return double(x); + } + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list2, QVector<double>() << 1.0 << 2.0 << 3.0); + + QVector<double> list3 = QtConcurrent::blockingMapped<QVector<double> >(QList<int>(list), + [](int x) { + return double(x); + } + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list3, QVector<double>() << 1.0 << 2.0 << 3.0); + + QStringList strings = QStringList() << "1" << "2" << "3"; + QVector<int> list4 = QtConcurrent::blockingMapped<QVector<int> >(strings, + [](const QString &string) { + return string.toInt(); + } + ); + QCOMPARE(list4, QVector<int>() << 1 << 2 << 3); + + QVector<int> list5 = QtConcurrent::blockingMapped<QVector<int> >(QStringList(strings), + [](const QString &string) { + return string.toInt(); + } + ); + QCOMPARE(list5, QVector<int>() << 1 << 2 << 3); + } } int intSquare(int x) @@ -892,8 +1109,6 @@ int intSquare(int x) class IntSquare { public: - typedef int result_type; - int operator()(int x) { return x * x; @@ -1088,6 +1303,211 @@ void tst_QtConcurrentMap::mappedReduced() } } +void tst_QtConcurrentMap::mappedReducedLambda() +{ + QList<int> list; + list << 1 << 2 << 3; + QList<Number> numberList; + numberList << 1 << 2 << 3; + + // lambda-lambda + { + int sum = QtConcurrent::mappedReduced<int>(list, + [](int x) { + return x * x; + }, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced<int>(list.constBegin(), list.constEnd(), + [](int x) { + return x * x; + }, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced<int>(QList<int>(list), + [](int x) { + return x * x; + }, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum3, 14); + } + + // lambda-functor + { + int sum = QtConcurrent::mappedReduced<int>(list, + [](int x) { + return x * x; + }, + IntSumReduce() + ); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced<int>(list.constBegin(), list.constEnd(), + [](int x) { + return x * x; + }, + IntSumReduce() + ); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced<int>(QList<int>(list), + [](int x) { + return x * x; + }, + IntSumReduce() + ); + QCOMPARE(sum3, 14); + } + + // functor-lambda + { + int sum = QtConcurrent::mappedReduced<int>(list, + IntSquare(), + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced<int>(list.constBegin(), list.constEnd(), + IntSquare(), + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced<int>(QList<int>(list), + IntSquare(), + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum3, 14); + } + + // lambda-function + { + int sum = QtConcurrent::mappedReduced<int>(list, + [](int x) { + return x * x; + }, + intSumReduce + ); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced<int>(list.constBegin(), list.constEnd(), + [](int x) { + return x * x; + }, + intSumReduce + ); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced<int>(QList<int>(list), + [](int x) { + return x * x; + }, + intSumReduce + ); + QCOMPARE(sum3, 14); + } + + // function-lambda + { + int sum = QtConcurrent::mappedReduced<int>(list, + intSquare, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::mappedReduced<int>(list.constBegin(), list.constEnd(), + intSquare, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::mappedReduced<int>(QList<int>(list), + intSquare, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum3, 14); + } + + // lambda-member + { + auto push_back = static_cast<void (QVector<int>::*)(const int &)>(&QVector<int>::push_back); + + QList<int> list2 = QtConcurrent::mappedReduced(list, + [](int x) { + return x * x; + }, + push_back, + OrderedReduce + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list2, QList<int>() << 1 << 4 << 9); + + QList<int> list3 = QtConcurrent::mappedReduced(list.constBegin(), list.constEnd(), + [](int x) { + return x * x; + }, + push_back, + OrderedReduce + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list3, QList<int>() << 1 << 4 << 9); + + QList<int> list4 = QtConcurrent::mappedReduced(QList<int>(list), + [](int x) { + return x * x; + }, + push_back, + OrderedReduce + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list4, QList<int>() << 1 << 4 << 9); + } + + // member-lambda + { + int sum = QtConcurrent::mappedReduced<int>(numberList, + &Number::toInt, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum, 6); + int sum2 = QtConcurrent::mappedReduced<int>(numberList.constBegin(), numberList.constEnd(), + &Number::toInt, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::mappedReduced<int>(QList<Number>(numberList), + &Number::toInt, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum3, 6); + } +} + void tst_QtConcurrentMap::blocking_mappedReduced() { QList<int> list; @@ -1273,6 +1693,213 @@ void tst_QtConcurrentMap::blocking_mappedReduced() } } +void tst_QtConcurrentMap::blocking_mappedReducedLambda() +{ + QList<int> list; + list << 1 << 2 << 3; + QList<Number> numberList; + numberList << 1 << 2 << 3; + + // lambda-lambda + { + int sum = QtConcurrent::blockingMappedReduced<int>(list, + [](int x) { + return x * x; + }, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced<int>(list.constBegin(), list.constEnd(), + [](int x) { + return x * x; + }, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced<int>(QList<int>(list), + [](int x) { + return x * x; + }, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum3, 14); + } + + // lambda-functor + { + int sum = QtConcurrent::blockingMappedReduced<int>(list, + [](int x) { + return x * x; + }, + IntSumReduce() + ); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced<int>(list.constBegin(), list.constEnd(), + [](int x) { + return x * x; + }, + IntSumReduce() + ); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced<int>(QList<int>(list), + [](int x) { + return x * x; + }, + IntSumReduce() + ); + QCOMPARE(sum3, 14); + } + + // functor-lambda + { + int sum = QtConcurrent::blockingMappedReduced<int>(list, + IntSquare(), + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced<int>(list.constBegin(), list.constEnd(), + IntSquare(), + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced<int>(QList<int>(list), + IntSquare(), + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum3, 14); + } + + // lambda-function + { + int sum = QtConcurrent::blockingMappedReduced(list, + [](int x) { + return x * x; + }, + intSumReduce + ); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced(list.constBegin(), list.constEnd(), + [](int x) { + return x * x; + }, + intSumReduce + ); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced(QList<int>(list), + [](int x) { + return x * x; + }, + intSumReduce + ); + QCOMPARE(sum3, 14); + } + + // function-lambda + { + int sum = QtConcurrent::blockingMappedReduced<int>(list, + intSquare, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum, 14); + int sum2 = QtConcurrent::blockingMappedReduced<int>(list.constBegin(), list.constEnd(), + intSquare, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 14); + + int sum3 = QtConcurrent::blockingMappedReduced<int>(QList<int>(list), + intSquare, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum3, 14); + } + + // lambda-member + { + auto push_back = static_cast<void (QVector<int>::*)(const int &)>(&QVector<int>::push_back); + + QList<int> list2 = QtConcurrent::blockingMappedReduced(list, + [](int x) { + return x * x; + }, + push_back, + OrderedReduce + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list2, QList<int>() << 1 << 4 << 9); + + QList<int> list3 = QtConcurrent::blockingMappedReduced(list.constBegin(), list.constEnd(), + [](int x) { + return x * x; + }, + push_back, + OrderedReduce + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list3, QList<int>() << 1 << 4 << 9); + + QList<int> list4 = QtConcurrent::blockingMappedReduced(QList<int>(list), + [](int x) { + return x * x; + }, + push_back, + OrderedReduce + ); + QCOMPARE(list, QList<int>() << 1 << 2 << 3); + QCOMPARE(list4, QList<int>() << 1 << 4 << 9); + } + + // member-lambda + { + std::function<void(int&, int)> sumRecuce = [](int &sum, int x) { + sum += x; + }; + + int sum = QtConcurrent::blockingMappedReduced(numberList, + &Number::toInt, + sumRecuce + ); + QCOMPARE(sum, 6); + int sum2 = QtConcurrent::blockingMappedReduced<int>(numberList.constBegin(), numberList.constEnd(), + &Number::toInt, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum2, 6); + + int sum3 = QtConcurrent::blockingMappedReduced<int>(QList<Number>(numberList), + &Number::toInt, + [](int &sum, int x) { + sum += x; + } + ); + QCOMPARE(sum3, 6); + } +} + int sleeper(int val) { QTest::qSleep(100); @@ -1646,6 +2273,35 @@ void tst_QtConcurrentMap::stlContainers() QtConcurrent::blockingMap(list, multiplyBy2Immutable); } +void tst_QtConcurrentMap::stlContainersLambda() +{ + std::vector<int> vector; + vector.push_back(1); + vector.push_back(2); + + std::vector<int> vector2 = QtConcurrent::blockingMapped<std::vector<int> >(vector, + [](const int &i) { + return mapper(i); + } + ); + QCOMPARE(vector2.size(), (std::vector<int>::size_type)(2)); + + std::list<int> list; + list.push_back(1); + list.push_back(2); + + std::list<int> list2 = QtConcurrent::blockingMapped<std::list<int> >(list, + [](const int &i) { + return mapper(i); + } + ); + QCOMPARE(list2.size(), (std::vector<int>::size_type)(2)); + + QtConcurrent::mapped(list, [](const int &i) { return mapper(i); }).waitForFinished(); + + QtConcurrent::blockingMap(list, [](int x) { x *= 2; }); +} + InstanceCounter ic_fn(const InstanceCounter & ic) { return InstanceCounter(ic); @@ -1730,7 +2386,6 @@ struct LockedCounter : mtx(mutex), ref(ai) {} - typedef int result_type; int operator()(int x) { QMutexLocker locker(mtx); diff --git a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp index c0782d8483..8f50329ec5 100644 --- a/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp +++ b/tests/auto/concurrent/qtconcurrentrun/tst_qtconcurrentrun.cpp @@ -104,7 +104,6 @@ public: int member0() { return 10; } int member1(int in) { return in; } - typedef int result_type; int operator()() { return 10; } int operator()(int in) { return in; } }; @@ -115,7 +114,6 @@ public: int member0() const { return 10; } int member1(int in) const { return in; } - typedef int result_type; int operator()() const { return 10; } int operator()(int in) const { return in; } }; @@ -126,7 +124,6 @@ public: int member0() noexcept { return 10; } int member1(int in) noexcept { return in; } - typedef int result_type; int operator()() noexcept { return 10; } int operator()(int in) noexcept { return in; } }; @@ -137,7 +134,6 @@ public: int member0() const noexcept { return 10; } int member1(int in) const noexcept { return in; } - typedef int result_type; int operator()() const noexcept { return 10; } int operator()(int in) const noexcept { return in; } }; @@ -320,7 +316,6 @@ void tst_QtConcurrentRun::returnValue() struct TestClass { void foo() { } - typedef void result_type; void operator()() { } void operator()(int) { } void fooInt(int){ }; @@ -329,7 +324,6 @@ struct TestClass struct TestConstClass { void foo() const { } - typedef void result_type; void operator()() const { } void operator()(int) const { } void fooInt(int) const { }; |