Created
December 1, 2018 17:27
-
-
Save estan/da18a02596dafc8ce04e61f76ef3604a to your computer and use it in GitHub Desktop.
QtConcurrent mapped lambda
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/concurrent/qtconcurrent_global.h b/src/concurrent/qtconcurrent_global.h | |
index b02abd63ea..f5c77f00ba 100644 | |
--- a/src/concurrent/qtconcurrent_global.h | |
+++ b/src/concurrent/qtconcurrent_global.h | |
@@ -54,6 +54,110 @@ QT_BEGIN_NAMESPACE | |
# define Q_CONCURRENT_EXPORT | |
#endif | |
+template <typename F> | |
+struct return_type_impl; | |
+ | |
+template <typename R, typename... Args> | |
+struct return_type_impl<R(Args...)> { using type = R; }; | |
+ | |
+template <typename R, typename... Args> | |
+struct return_type_impl<R(Args..., ...)> { using type = R; }; | |
+ | |
+template <typename R, typename... Args> | |
+struct return_type_impl<R(*)(Args...)> { using type = R; }; | |
+ | |
+template <typename R, typename... Args> | |
+struct return_type_impl<R(*)(Args..., ...)> { using type = R; }; | |
+ | |
+template <typename R, typename... Args> | |
+struct return_type_impl<R(&)(Args...)> { using type = R; }; | |
+ | |
+template <typename R, typename... Args> | |
+struct return_type_impl<R(&)(Args..., ...)> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...)> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...)> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) &> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) &> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) &&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) &&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) const> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) const> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) const&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) const&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) const&&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) const&&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) volatile> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) volatile> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) volatile&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) volatile&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) volatile&&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) volatile&&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) const volatile> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) const volatile> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) const volatile&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) const volatile&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args...) const volatile&&> { using type = R; }; | |
+ | |
+template <typename R, typename C, typename... Args> | |
+struct return_type_impl<R(C::*)(Args..., ...) const volatile&&> { using type = R; }; | |
+ | |
+template <typename T, typename = void> | |
+struct return_type | |
+ : return_type_impl<T> {}; | |
+ | |
+template <typename T> | |
+struct return_type<T, decltype(void(&T::operator()))> | |
+ : return_type_impl<decltype(&T::operator())> {}; | |
+ | |
+template <typename T> | |
+using return_type_t = typename return_type<T>::type; | |
+ | |
QT_END_NAMESPACE | |
#endif // include guard | |
diff --git a/src/concurrent/qtconcurrentfunctionwrappers.h b/src/concurrent/qtconcurrentfunctionwrappers.h | |
index 0f9eb46999..45f093aca3 100644 | |
--- a/src/concurrent/qtconcurrentfunctionwrappers.h | |
+++ b/src/concurrent/qtconcurrentfunctionwrappers.h | |
@@ -41,6 +41,7 @@ | |
#define QTCONCURRENT_FUNCTIONWRAPPERS_H | |
#include <QtConcurrent/qtconcurrentcompilertest.h> | |
+#include <QtConcurrent/qtconcurrent_global.h> | |
#include <QtCore/QStringList> | |
#if !defined(QT_NO_CONCURRENT) || defined(Q_CLANG_QDOC) | |
@@ -234,10 +235,8 @@ struct PushBackWrapper | |
#endif | |
}; | |
-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; }; | |
+struct LazyResultType { using Type = return_type_t<Functor>; }; | |
template <class T> | |
struct ReduceResultType; | |
diff --git a/src/concurrent/qtconcurrentmapkernel.h b/src/concurrent/qtconcurrentmapkernel.h | |
index e8df668791..a0796ac7f4 100644 | |
--- a/src/concurrent/qtconcurrentmapkernel.h | |
+++ b/src/concurrent/qtconcurrentmapkernel.h | |
@@ -159,10 +159,10 @@ public: | |
}; | |
template <typename Iterator, typename MapFunctor> | |
-class MappedEachKernel : public IterateKernel<Iterator, typename MapFunctor::result_type> | |
+class MappedEachKernel : public IterateKernel<Iterator, return_type_t<MapFunctor>> | |
{ | |
MapFunctor map; | |
- typedef typename MapFunctor::result_type T; | |
+ using T = return_type_t<MapFunctor>; | |
public: | |
typedef T ReturnType; | |
typedef T ResultType; | |
diff --git a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp | |
index b864b065e6..d537e0f59b 100644 | |
--- a/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp | |
+++ b/tests/auto/concurrent/qtconcurrentmap/tst_qtconcurrentmap.cpp | |
@@ -436,6 +436,15 @@ void tst_QtConcurrentMap::mapped() | |
QLinkedList<Number> numberLinkedList; | |
numberLinkedList << 1 << 2 << 3; | |
+ // lambda | |
+ { | |
+ int factor = 2; | |
+ QList<int> list2 = QtConcurrent::mapped(list, [factor](int v) { return v * factor ; }).results(); | |
+ QCOMPARE(list, QList<int>() << 1 << 2 << 3); | |
+ QCOMPARE(list2, QList<int>() << 2 << 4 << 6); | |
+ | |
+ // TODO: More tests... | |
+ } | |
// functor | |
{ | |
QList<int> list2 = QtConcurrent::mapped(list, MultiplyBy2()).results(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment