PDA

View Full Version : Using lambdas with QtConcurrent::blockingMappedReduced does not compile



gemmell
6th June 2013, 03:44
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:



typedef QMap<QString, int> WordCount;

void ClassName::ProcessStuff() {
auto wordMapFn = [&](const QString &file) -> WordCount {
QFile f(file);
f.open(QIODevice::ReadOnly);
QTextStream textStream(&f);
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();
}
};
QStringList files;
WordCount total = QtConcurrent::blockingMappedReduced(files.begin(), files.end(), wordMapFn, wordReduceFn);
}

Compiling this in VS2012 with Qt5.0.2 produces the following error:


1>Implementation\ImportExport\OpcExporter.cpp(250): error C2893: Failed to specialize function template 'QtPrivate::ReduceResultType<ReduceFunctor>::ResultType QtConcurrent::blockingMappedReduced(Iterator,Itera tor,MapFunctor,ReduceFunctor,QtConcurrent::ReduceO ptions)'
1> With the following template arguments:
1> 'QList<T>::iterator'
1> with
1> [
1> T=QString
1> ]
1> 'ImportExport::OpcExporter::CreateProjectChildAndA ttachedParts::<lambda_34d77ea4bb1263c3043c2eae1f2efb26>'
1> 'ImportExport::OpcExporter::CreateProjectChildAndA ttachedParts::<lambda_0b977c9c36b310423ccf2f5f1c540fb3>'
1>Implementation\ImportExport\OpcExporter.cpp(250): error C2783: 'ResultType QtConcurrent::blockingMappedReduced(Iterator,Itera tor,MapFunctor,ReduceFunctor,QtConcurrent::ReduceO ptions)' : could not deduce template argument for 'ResultType'
1> c:\qt\qt5.0.2\5.0.2\msvc2012_64\include\qtconcurre nt\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::ReduceOpti ons)'
1> With the following template arguments:
1> 'QList<T>::iterator'
1> with
1> [
1> T=QString
1> ]
1> 'ImportExport::OpcExporter::CreateProjectChildAndA ttachedParts::<lambda_34d77ea4bb1263c3043c2eae1f2efb26>'
1> 'QList<T>::iterator'
1> with
1> [
1> T=QString
1> ]
1>Implementation\ImportExport\OpcExporter.cpp(250): error C2783: 'ResultType QtConcurrent::blockingMappedReduced(const Sequence &,MapFunctor,ReduceFunctor,QtConcurrent::ReduceOpti ons)' : could not deduce template argument for 'ResultType'
1> c:\qt\qt5.0.2\5.0.2\msvc2012_64\include\qtconcurre nt\qtconcurrentmap.h(208) : see declaration of 'QtConcurrent::blockingMappedReduced'
1>
1>Build FAILED.


Any help much appreciated.

anda_skoa
6th June 2013, 12:06
Try calling with the template type explicitly specified, I guess something like



WordCount total = QtConcurrent::blockingMappedReduced<WordCount>(files.begin(), files.end(), wordMapFn, wordReduceFn);


Cheers,
_

gemmell
7th June 2013, 04:44
Ah of course. Yes that worked. Thanks.

gemmell
10th June 2013, 14:37
I spoke too soon:


void MyClass::MyFunc() {
typedef QMap<QString, int> WordCount;


auto wordMapFn = [&](const QString &file) -> WordCount {
QFile f(file);
f.open(QIODevice::ReadOnly);
QTextStream textStream(&f);
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();
}
};
QStringList files;
WordCount total = QtConcurrent::blockingMappedReduced<WordCount>(files.begin(), files.end(), wordMapFn, wordReduceFn);
}


gives me this error:



1>c:\qt\qt5.0.2\5.0.2\msvc2012_64\include\qtconcurre nt\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:


std::function<WordCount (const QString&)> wordMapFn = [&](const QString &file) -> WordCount {
...
};


Hope this helps others.

anda_skoa
10th June 2013, 17:05
Could also be a temporary compiler limitation. The C++11 stuff is relatively new.

Cheers,
_

Phlucious
3rd February 2016, 01:32
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.