Skip to content

Instantly share code, notes, and snippets.

@estan
Created December 1, 2018 17:27
Show Gist options
  • Save estan/da18a02596dafc8ce04e61f76ef3604a to your computer and use it in GitHub Desktop.
Save estan/da18a02596dafc8ce04e61f76ef3604a to your computer and use it in GitHub Desktop.
QtConcurrent mapped lambda
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