Reputation: 847
I want to use QtConcurrent::mapped
to process a std::vector
of data in parallel. Everything seems to work fine when I use a free function as the MapFunctor
argument to QtConcurrent::mapped
. However, when I use a lambda or a member pointer, the future returned is a QFuture<void>
, not a QFuture
of the result type. Below is a minimal reproducible example:
#include <QtConcurrent>
int free_func(int x) { return x + 3; }
struct S {
int x;
int func(S y) { return x + y.x; }
};
void example() {
std::vector<int> v = {1, 2, 3};
QFuture<int> f1 = QtConcurrent::mapped(v, free_func);
QFuture<int> f2 = QtConcurrent::mapped(v, [](int x) { return x + 1; });
std::vector<S> v2 = {S{1}, S{2}, S{3}};
QFuture<int> f3 = QtConcurrent::mapped(v2, &S::func);
}
As far as I can tell from reading the Qt documentation, this should all be fine. However, I get compilation errors for f2
and f3
that read
.../test.cpp:15: error: conversion from ‘QFuture<void>’ to non-scalar type ‘QFuture<int>’ requested
.../test.cpp: In function ‘void example()’:
.../test.cpp:15:41: error: conversion from ‘QFuture<void>’ to non-scalar type ‘QFuture<int>’ requested
15 | QFuture<int> f2 = QtConcurrent::mapped(v, [](int x) { return x + 1; });
| ~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
and something similar for f3
. Why should f2
and f3
QFuture<void>
instead of QFuture<int>
?
(I know I have to actually use the futures after creating them, my question is just about the types of the futures.)
Upvotes: 0
Views: 397
Reputation: 20938
Version with S::func
doesn't work because func
has wrong signature.
If you have a collection C
, mapped
function iterates over all elements in this collection calling passed member function for each instance of C
.
vector<S> C{S(1),S(2),..};
by
mapped(C,&S::func)
will be performed:
C[0].func();
C[1].func();
...
where above calls are performed by map-function whose signature is:
RetType mapFunction(const S&)
member function is invoked for const object, so should be marked as const too.
struct S {
int x;
int func() const { return x + 1; } // + const and no arguments
};
void example() {
std::vector<S> v2 {S{1}, S{2}, S{3}};
QFuture<int> f3 = QtConcurrent::mapped(v2, &S::func);
Is fine.
Upvotes: 2
Reputation: 958
The automatic type deduction does not work with lambdas, you have to pass a proper std::function
std::function<int(int)> f = [](int x) { return x + 1; }; QFuture<int> f2 = QtConcurrent::mapped(v, f);
f3 can't work since S::func() is no static function and therefore can't be used here.
Upvotes: 2