2011-10-31 30 views
1

这是我第一次尝试使用QtConcurrent :: blockingMappedReduced,并且我无法在MSVC 2010 Express(使用QT 4.7.1源代码)中构建它。QtConcurrent blockingMappedReduced error

我创建了一个小例子,类似于我的实际代码,并有同样的问题建筑:

// Here's the general outline: 
// 1. create a list of random numbers 
// 2. pass the list to blockingMappedReduced 
// 3. the map function calculates the sine of the given random number 
// 4. the reduce function finds the random number with the maximum sine value 

// Here's the implementation: 

#include "stdafx.h" 
#include <qlist.h> 
#include <qtconcurrentmap.h> 

// My class for the map/reduce functions 
class myClass 
{ 
private: 

    // Nested class to hold the intermediate results from the map function 
    // I think I need this because the reduce function needs more from the map function than a single return value 
    class Temp 
    { 
    public: 

     // For example, let's pass these two member variables from the map function to the reduce function 
     int randomInput; 
     double resultingOutput; 

     // The Temp constructor 
     Temp::Temp(double randomInput, double resultingOutput) 
     { 
      this->randomInput = randomInput; 
      this->resultingOutput = resultingOutput; 
     } 
    }; 

public: 

    // For example, these myClass members will hold the final result from the reduce function 
    double maximumOutput; 
    double maximumInput; 

    // The myClass constructor 
    myClass::myClass() 
    { 
     this->maximumOutput = -1; 
    } 

    // The map function 
    const Temp mapFunction(const double& randomInput) 
    { 
     // For example, let's calculate the sine of the given random number 
     double resultingOutput = sin(randomInput); 

     // Construct the temporary structure to pass multiple values to the reduce function 
     const Temp temp(randomInput, resultingOutput); 
     return(temp); 
    } 

    // The reduce function 
    void reduceFunction(double& maxInput, const Temp& temp) 
    { 
     // For example, let's find the maximum computed sine value 
     if (temp.resultingOutput > this->maximumOutput) 
     { 
      this->maximumOutput = temp.resultingOutput; 
      this->maximumInput = temp.randomInput; 
     } 

     maxInput = this->maximumInput; 
    } 
}; 

// Main function 
void main(int argc, _TCHAR* argv[]) 
{ 
    // Build a list of random numbers 
    QList<int> aList; 
    for (int count = 8; count > 0; --count) 
    { 
     aList.append(rand()); 
    } 

    // Invoke the parallel map/reduce function 
    myClass myClassInstance; 
    double theAnswer = QtConcurrent::blockingMappedReduced(aList, &myClass::mapFunction, &myClass::reduceFunction); 
} 

编译器抱怨的最后一行,在那里blockingMappedReduced被调用。

c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'D QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__thiscall C::*)(void) const,U (__thiscall D::*)(V),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(659) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'C QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__cdecl *)(U),V (__thiscall C::*)(W),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(643) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'V QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__thiscall C::*)(void) const,U (__cdecl *)(V &,W),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(627) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'W QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__cdecl *)(U),V (__cdecl *)(W &,X),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(611) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'ResultType QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__thiscall C::*)(void) const,ReduceFunctor,QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(595) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'ResultType QtConcurrent::blockingMappedReduced(Iterator,Iterator,T (__cdecl *)(U),ReduceFunctor,QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(579) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'C QtConcurrent::blockingMappedReduced(Iterator,Iterator,MapFunctor,T (__thiscall C::*)(U),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(563) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'U QtConcurrent::blockingMappedReduced(Iterator,Iterator,MapFunctor,T (__cdecl *)(U &,V),QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(547) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2780: 'ResultType QtConcurrent::blockingMappedReduced(Iterator,Iterator,MapFunctor,ReduceFunctor,QtConcurrent::ReduceOptions)' : expects 5 arguments - 3 provided 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(536) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'D QtConcurrent::blockingMappedReduced(const Sequence &,T (__thiscall C::*)(void) const,U (__thiscall D::*)(V),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__thiscall C::*)(void) const' from 'const myClass::Temp (__thiscall myClass::*)(const double &)' 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(522) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'C QtConcurrent::blockingMappedReduced(const Sequence &,T (__cdecl *)(U),V (__thiscall C::*)(W),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__cdecl *)(U)' from 'const myClass::Temp (__thiscall myClass::*)(const double &)' 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(508) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'V QtConcurrent::blockingMappedReduced(const Sequence &,T (__thiscall C::*)(void) const,U (__cdecl *)(V &,W),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__thiscall C::*)(void) const' from 'const myClass::Temp (__thiscall myClass::*)(const double &)' 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(494) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'W QtConcurrent::blockingMappedReduced(const Sequence &,T (__cdecl *)(U),V (__cdecl *)(W &,X),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__cdecl *)(U)' from 'const myClass::Temp (__thiscall myClass::*)(const double &)' 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(480) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'ResultType QtConcurrent::blockingMappedReduced(const Sequence &,T (__thiscall C::*)(void) const,ReduceFunctor,QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__thiscall C::*)(void) const' from 'const myClass::Temp (__thiscall myClass::*)(const double &)' 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(466) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'ResultType QtConcurrent::blockingMappedReduced(const Sequence &,T (__cdecl *)(U),ReduceFunctor,QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__cdecl *)(U)' from 'const myClass::Temp (__thiscall myClass::*)(const double &)' 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(452) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'C QtConcurrent::blockingMappedReduced(const Sequence &,MapFunctor,T (__thiscall C::*)(U),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__thiscall C::*)(U)' from 'void (__thiscall myClass::*)(double &,const myClass::Temp &)' 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(438) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2784: 'U QtConcurrent::blockingMappedReduced(const Sequence &,MapFunctor,T (__cdecl *)(U &,V),QtConcurrent::ReduceOptions)' : could not deduce template argument for 'T (__cdecl *)(U &,V)' from 'void (__thiscall myClass::*)(double &,const myClass::Temp &)' 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(424) : see declaration of 'QtConcurrent::blockingMappedReduced' 
c:\gwa\tmp\stackoverflow\stackoverflow\stackoverflow.cpp(77): error C2783: 'ResultType QtConcurrent::blockingMappedReduced(const Sequence &,MapFunctor,ReduceFunctor,QtConcurrent::ReduceOptions)' : could not deduce template argument for 'ResultType' 
      c:\gwa\third_party\qt\qt-4.7.1\src\corelib\concurrent\qtconcurrentmap.h(414) : see declaration of 'QtConcurrent::blockingMappedReduced' 

从网上QT文档(http://doc.qt.nokia.com/4.7-snapshot/qtconcurrentmap.html#blockingMappedReduced),这里的原型:

T blockingMappedReduced (const Sequence & sequence, MapFunction mapFunction, ReduceFunction reduceFunction, QtConcurrent::ReduceOptions reduceOptions = UnorderedReduce | SequentialReduce) 

我害怕我没有专业知识去调试。任何帮助将不胜感激。再一次,因为我的C++技能不是专家,所以帮助需要明确以便我理解它(例如,实际的代码片段,而不是那些比我有更多知识的东西,比如“你的论点必须是一个常量引用” )。

在此先感谢您的帮助。

回答

2

您的代码有一些常见问题需要修补,而不是与QtConcurrent相关。首先,你应该没有资格的构造函数,所以不是:

// The Temp constructor 
    Temp::Temp(double randomInput, double resultingOutput) 

你只要简单地写:

// The Temp constructor 
    Temp(double randomInput, double resultingOutput) 

同为myClass。另外,main的函数签名应始终返回int,但在C99和C++中,如果要返回0,则可以省略return语句(但我总是明确地将return 0作为个人偏好设置。)

What should main() return in C and C++?

至于你QtConcurrent问题,有几个。首先你的QList是整数,文档指出序列中的类型应该和map函数的第一个参数相匹配(如果你有双精度的话)。所以QList需要改变为双 - 或 - 你的地图功能需要一个整数。

你有另外一个问题是,你正在试图指向成员函数传递到意想不到只是纯醇功能插槽的事实:

// Invoke the parallel map/reduce function 
    myClass myClassInstance; 
    double theAnswer = QtConcurrent::blockingMappedReduced(aList, 
     &myClass::mapFunction, &myClass::reduceFunction); 

注意,不存在myClassInstance提到除了声明。在一般情况下...解决这个问题并不像改变呼叫使用&myClassInstance::mapFunction, &myClassInstance::reduceFunction那么简单。当你位于C环顾四周++,你会发现没有制造出能适合任何插槽一个函数调用的对象通常可行的方法,即使它们被设计用来似乎是调用类的函数:

Help with boost bind/functions

幸运的是,QtConcurrent并没有在这个角落描绘你。它预期的函数对象的需要:

http://doc.qt.io/archives/qt-4.7/qtconcurrentmap.html#using-function-objects

但是,而不是挖掘到如何使这项工作,我们应该考虑你为什么会想这些是摆在首位的成员函数。 Map/Reduce模型可以让你定义自定义的累加器和结果类型,并且可以毫无问题地得到你想要的结果。这里有一个简单的版本,希望能编译,让你更接近:

#include <qlist.h> 
#include <qtconcurrentmap.h> 

#include <cmath> // for sin() 
#include <algorithm> // for min, max, etc. 
#include <limits> // for numeric_limits 

struct MapResult // same as class, but "public" by default 
{ 
    double input; 
    double output; 

    // must be "default constructible" due to guts of QtConcurrent :-/  
    // implementation artifact, don't worry about it affecting you... 
    MapResult() {} 

    MapResult (double input, double output) : 
     // initializing members like this is cleaner than this->x = x... 
     // and for certain members you HAVE to do it this way 
     input (input), output (output) 
    { 
    } 
}; 

struct ReduceAccumulator // same as class, but "public" by default 
{ 
    MapResult largest; 

    ReduceAccumulator() : 
     // a better choice than 0 for an "uninitialized max" since 
     // any other double will be larger...but you really should 
     // probably accomodate a "no entries" case 
     largest (MapResult (0, std::numeric_limits<double>::min()) 
    { 
    } 
}; 

// pattern of return type should be "U", not "const U" according to docs 
MapResult mapFunction(const double& input) 
{ 
    // no need to construct a named local var if you don't want to 
    // also no parentheses needed on return(x); ... return x; is fine 
    return MapResult (input, sin(input)); 
} 

void reduceFunction(ReduceAccumulator& acc, const MapResult& oneResult) 
{ 
    if (oneResult.output > acc.largest.output) { 
     acc.largest = oneResult 
    } 
} 

int main(int argc, char* argv[]) 
{ 
    QList<double> aList; 
    for (int count = 8; count > 0; --count) 
    { 
     aList.append(rand()); 
    } 

    ReduceAccumulator answer = QtConcurrent::blockingMappedReduced(
     aList, &mapFunction, &reduceFunction); 

    return 0; 
} 

包括一些通用的C++的笔记,希望能有所帮助......


UPDATE:他们提供另一条路线呢使用成员函数,但它会根据您尝试编写的样式进行一些不同的假设。首先,它假定你的序列输入类型是一个类(double是“POD”或“普通旧数据”类型并且没有方法调度)。那么该参数是隐含的。

但请注意,如果你想使用这种技术,它会以特定的方式风格化代码。这里是变化:

struct ReduceAccumulator 
{ 
    MapResult largest; 

    ReduceAccumulator() : 
     largest (MapResult(0, std::numeric_limits<double>::min()) 
    { 
    } 

    // runs on non-const object, and drops first parameter (now implicit) 
    void reduceFunction(const MapResult& oneResult) 
    { 
     if (oneResult.output > largest.output) { 
      largest = oneResult 
     } 
    } 
}; 

struct MyDouble { 
    double d; 

    MyDouble (double d) : d (d) {} 

    // as member it takes no arguments, and needs to run on const objects 
    MapResult mapFunction() const 
    { 
     return MapResult (d, sin(d)); 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    // to use a member as mapFunction, must be a member of input sequence type 
    QList<MyDouble> aList; 
    for (int count = 8; count > 0; --count) 
    { 
     aList.append(MyDouble (rand())); 
    } 

    ReduceAccumulator theAnswer = QtConcurrent::blockingMappedReduced(
     aList, &MyDouble::mapFunction, &ReduceAccumulator::reduceFunction); 
} 

你可以挑选...在这种情况下,可能会更好地做reduceFunction作为成员。但是要改变输入序列类型很丑陋,而且这不是过程参数的正确位置 - 你需要一个函数对象。

(的同时也要记住,一个可写状态,地图功能可以得到破坏的MapReduce并行性。该地图操作都应该让他们保持独立,真正只能通过他们的结果产生输出...)

+0

HostileFork:感谢您的解决方案。除了一般的C++清理以外,下面是与blockingMappedReduced相关的问题:1)map和reduce函数不能成为成员函数,但必须是全局函数,2)我的中间类从地图传递值函数的reduce函数需要一个默认的构造函数,3)map函数的类型不是const。后续问题:QT文档给出了一个使用map和reduce为QtConcurrent :: mappedReduced使用成员函数的示例。但是这不适用于blockingMappedReduced? – user1020872

+0

要回答我自己的后续问题,使用成员函数时,显然它们必须是静态的。 – user1020872

+0

我可以问你一些关于你的C++清理我的代码的问题吗? 1)为什么中间对象使用结构而不是类是可取的? 2)为什么最好没有中间对象的嵌套类?我的动机是,我的实际代码中的myClass是封装了许多其他事物的类,而不仅仅是我在示例中展示的简单事物。 – user1020872

2

HostileFork:再次感谢您的帮助。你让我重返正轨,让我真正的代码工作。

为了完整起见,下面是我的原始示例,其中需要进行最小的更改,以便进行blockingMappedReduced工作(但仍然伴随着我乱七八糟的C++样式问题)。这就是我通过解决方案来理解什么是什么的。它可能帮助其他人排序通过哪些阻塞映射减少的问题,哪些是C++问题:

#include "stdafx.h" 
#include <qlist.h> 
#include <qtconcurrentmap.h> 


// My class for the map/reduce functions 
class myClass 
{ 
    // Nested class to hold the intermediate results from the map function 
    // I think I need this because the reduce function needs more from the map function than a single return value 
    class Temp 
    { 
    public: 

     // For example, let's pass these two member variables from the map function to the reduce function 
     int randomInput; 
     double resultingOutput; 

     // default Temp constructor 
     Temp() 
     { 
     }; 

     // The Temp constructor 
     Temp(double randomInput, double resultingOutput) 
     { 
      this->randomInput = randomInput; 
      this->resultingOutput = resultingOutput; 
     } 
    }; 

public: 

    // For example, these myClass members will hold the final result from the reduce function 
    double maximumOutput; 
    double maximumInput; 

    // The myClass constructor 
    myClass() 
    { 
     this->maximumOutput = -1; 
    } 

    // The map function 
    static Temp myClass::mapFunction(const int& randomInput) 
    { 
     // For example, let's calculate the sine of the given random number 
     double resultingOutput = sin((double)randomInput); 

     // Construct the temporary structure to pass multiple values to the reduce function 
     Temp temp(randomInput, resultingOutput); 
     return(temp); 
    } 

    // The reduce function 
    static void myClass::reduceFunction(myClass& accumulator, const Temp& temp) 
    { 
     // For example, let's find the maximum computed sine value 
     if (temp.resultingOutput > accumulator.maximumOutput) 
     { 
      accumulator.maximumOutput = temp.resultingOutput; 
      accumulator.maximumInput = temp.randomInput; 
     } 
    } 
}; 


// Main function 
int main(int argc, _TCHAR* argv[]) 
{ 
    // Build a list of random numbers 
    QList<int> aList; 
    for (int count = 8; count > 0; --count) 
    { 
     aList.append(rand()); 
    } 

    // Invoke the parallel map/reduce function 
    myClass theAnswer = QtConcurrent::blockingMappedReduced(aList, &myClass::mapFunction, &myClass::reduceFunction); 

    return(0); 
} 
+0

啊,起初我并没有意识到你想要最大的结果输入(没有找到最大的输入和输出)。虽然你可以重命名变量来尝试做出更明显的事情,但请注意,如果你已经声明了MapResult类型,那么你可以重新使用这种类型......我改变了我的代码来做到这一点。还要注意对构造函数的更改('Temp :: Temp' =>'Temp')和main的返回类型不是多余的。无论MSVC 2010是否愿意为您编译,它都是不正确的C++,并且不会在符合标准的编译器上编译。 – HostileFork

+0

再次感谢您的建议。在我的实际代码中,我没有在一个文件中包含所有内容,构造函数原型位于头文件中,实现位于cpp文件中,并且原型按照您的建议。而我的实际主要功能确实返回一个int状态。但我的例子可能会让其他人阅读它,所以我会编辑它。 – user1020872