Using lambdas with QtConcurrent::blockingMappedReduced does not compile
Hello, I've been trying to get QtConcurrent::blockingMappedReduced to run using a couple of lambda's and keep running into a compile issue which I can't get to the bottom of. I've cut it right back and am currently using Qt's own example code converted into lambda's and getting the same error. So here it is:
Code:
typedef QMap<QString, int> WordCount;
void ClassName::ProcessStuff() {
auto wordMapFn
= [&](const QString &file
) -> WordCount
{ WordCount wordCount;
while (textStream.atEnd() == false)
foreach
(QString word, textStream.
readLine().
split(" ")) wordCount[word] += 1;
return wordCount;
};
auto wordReduceFn = [&](WordCount &result, const WordCount &w) {
QMapIterator<QString, int> i(w);
while (i.hasNext()) {
i.next();
result[i.key()] += i.value();
}
};
WordCount total = QtConcurrent::blockingMappedReduced(files.begin(), files.end(), wordMapFn, wordReduceFn);
}
Compiling this in VS2012 with Qt5.0.2 produces the following error:
Code:
1>Implementation\ImportExport\OpcExporter.cpp(250): error C2893: Failed to specialize function template 'QtPrivate::ReduceResultType<ReduceFunctor>::ResultType QtConcurrent::blockingMappedReduced(Iterator,Iterator,MapFunctor,ReduceFunctor,QtConcurrent::ReduceOptions)'
1> With the following template arguments:
1> 'QList<T>::iterator'
1> with
1> [
1> ]
1> 'ImportExport::OpcExporter::CreateProjectChildAndAttachedParts::<lambda_34d77ea4bb1263c3043c2eae1f2efb26>'
1> 'ImportExport::OpcExporter::CreateProjectChildAndAttachedParts::<lambda_0b977c9c36b310423ccf2f5f1c540fb3>'
1>Implementation\ImportExport\OpcExporter.cpp(250): error C2783: 'ResultType QtConcurrent::blockingMappedReduced(Iterator,Iterator,MapFunctor,ReduceFunctor,QtConcurrent::ReduceOptions)' : could not deduce template argument for 'ResultType'
1> c:\qt\qt5.0.2\5.0.2\msvc2012_64\include\qtconcurrent\qtconcurrentmap.h(237) : see declaration of 'QtConcurrent::blockingMappedReduced'
1>Implementation\ImportExport\OpcExporter.cpp(250): error C2893: Failed to specialize function template 'QtPrivate::ReduceResultType<ReduceFunctor>::ResultType QtConcurrent::blockingMappedReduced(const Sequence &,MapFunctor,ReduceFunctor,QtConcurrent::ReduceOptions)'
1> With the following template arguments:
1> 'QList<T>::iterator'
1> with
1> [
1> ]
1> 'ImportExport::OpcExporter::CreateProjectChildAndAttachedParts::<lambda_34d77ea4bb1263c3043c2eae1f2efb26>'
1> 'QList<T>::iterator'
1> with
1> [
1> ]
1>Implementation\ImportExport\OpcExporter.cpp(250): error C2783: 'ResultType QtConcurrent::blockingMappedReduced(const Sequence &,MapFunctor,ReduceFunctor,QtConcurrent::ReduceOptions)' : could not deduce template argument for 'ResultType'
1> c:\qt\qt5.0.2\5.0.2\msvc2012_64\include\qtconcurrent\qtconcurrentmap.h(208) : see declaration of 'QtConcurrent::blockingMappedReduced'
1>
1>Build FAILED.
Any help much appreciated.
Re: Using lambdas with QtConcurrent::blockingMappedReduced does not compile
Try calling with the template type explicitly specified, I guess something like
Code:
WordCount total = QtConcurrent::blockingMappedReduced<WordCount>(files.begin(), files.end(), wordMapFn, wordReduceFn);
Cheers,
_
Re: Using lambdas with QtConcurrent::blockingMappedReduced does not compile
Ah of course. Yes that worked. Thanks.
Re: Using lambdas with QtConcurrent::blockingMappedReduced does not compile
I spoke too soon:
Code:
void MyClass::MyFunc() {
typedef QMap<QString, int> WordCount;
auto wordMapFn
= [&](const QString &file
) -> WordCount
{ WordCount wordCount;
while (textStream.atEnd() == false)
foreach
(QString word, textStream.
readLine().
split(" ")) wordCount[word] += 1;
return wordCount;
};
auto wordReduceFn = [&](WordCount &result, const WordCount &w) {
QMapIterator<QString, int> i(w);
while (i.hasNext()) {
i.next();
result[i.key()] += i.value();
}
};
WordCount total = QtConcurrent::blockingMappedReduced<WordCount>(files.begin(), files.end(), wordMapFn, wordReduceFn);
}
gives me this error:
Code:
1>c:\qt\qt5.0.2\5.0.2\msvc2012_64\include\qtconcurrent\qtconcurrentmapkernel.h(116): error C2039: 'result_type' : is not a member of 'ImportExport::MyClass::MyFunc::<lambda_fa3d57d9b3ee2c79a98275b7637f0691>' (Implementation\ImportExport\MyClass.cpp)
...
The problem is that you can't use the auto keyword for the lambda's or it gets confused. So you have to fully specify the lambdas type:
Code:
std
::function<WordCount
(const QString
&)> wordMapFn
= [&](const QString &file
) -> WordCount
{ ...
};
Hope this helps others.
Re: Using lambdas with QtConcurrent::blockingMappedReduced does not compile
Could also be a temporary compiler limitation. The C++11 stuff is relatively new.
Cheers,
_
Re: Using lambdas with QtConcurrent::blockingMappedReduced does not compile
For future folks referring to this thread, I found that the std::function<> requirement was definitely and only true if the lambda had a return type, such as for the Mapped functor. Because the return type of the Reduced functor was void, std::function wasn't required.
I was compiling with MSVC2010.