Ваш код имеет несколько общих проблем для исправления, которые не связаны с QtConcurrent. Во-первых, вы не должны квалифицировать конструкторов, поэтому вместо:
// The Temp constructor
Temp::Temp(double randomInput, double resultingOutput)
Вы должны написать просто:
// The Temp constructor
Temp(double randomInput, double resultingOutput)
То же самое для myClass
. Кроме того, ваша сигнатура функции для main всегда должна возвращать int
, хотя в C99 и C ++ вы можете опустить оператор return, если хотите вернуть 0. (Однако я всегда явно ставлю return 0
в качестве личного предпочтения. ) * +1010 *
Что должно возвращать main () в C и C ++?
Что касается ваших проблем с QtConcurrent, есть пара. Сначала ваш QList состоит из целых чисел, и в документации указывается, что тип в последовательности должен соответствовать первому параметру функции карты (где у вас есть двойное число). Таким образом, QList должен быть изменен на двойной или ваша функция карты должна принимать int.
Другая проблема, с которой вы столкнулись, заключается в том, что вы пытаетесь передать указатели на функции-члены в слоты, которые ожидают только обычные функции:
// Invoke the parallel map/reduce function
myClass myClassInstance;
double theAnswer = QtConcurrent::blockingMappedReduced(aList,
&myClass::mapFunction, &myClass::reduceFunction);
Обратите внимание, что кроме декларации нет упоминания о myClassInstance
. В общем случае ... обойти это не так просто, как изменить вызов на &myClassInstance::mapFunction, &myClassInstance::reduceFunction
. Оглядываясь на C ++, вы обнаружите, что не существует вообще работоспособного способа сделать объекты, которые могут поместиться в любой слот, который может вызвать вызов функции, даже если они разработаны так, чтобы выглядеть как вызываемые функции:
Помощь с форсированным связыванием / функциями
К счастью, 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 ++, надеюсь, полезные ...
ОБНОВЛЕНИЕ : Другой маршрут, который они предлагают , использует функции-члены, но делает несколько других предположений из стиля, который вы пытались написать. Во-первых, предполагается, что ваш тип ввода последовательности является классом (double
является типом «POD» или «plain-old-data» и не имеет метода диспетчеризации). Тогда параметр неявный.
Но учтите, что если вы захотите использовать эту технику, она будет стилизовать код определенным образом. Вот изменения:
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);
}
Вы можете выбрать и выбрать ... в этом случае, вероятно, лучше использовать функцию limitFunction в качестве члена. Но уродливо менять тип входной последовательности, а это не то место, где параметры процесса могут быть полезны - вам нужен объект функции.
(Имейте также в виду, что доступное для записи состояние, которое может получить функция карты, подрывает параллелизм MapReduce. Предполагается, что операции с картой действительно генерируют выходные данные только через свой результат, поэтому они остаются независимыми ...)