Mafura
Mafura

Reputation: 23

Using QtConcurrent::MappedReduce in a class

I am currently learning QtConncurrenct for multi threaded applications. So for testing purposes I decided to implement a simple program that sums integers in a list, here is the code:

#include <QCoreApplication>
#include <QtConcurrent>
#include <functional>

class intObj{
    int m_value;
public:
    intObj(int val = 0):m_value(val){}

    int val() const {return m_value;}

};

static intObj mapFunction(const intObj &num){
    return intObj(num.val());
}

static void reduceFunction(intObj &sum, const intObj &term){
    int x = sum.val();
    int y = term.val();
    sum = intObj(x+y);
}


class myTest{
    public:
    int getSum(QList<intObj> numbers);

};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QList<intObj> n;

    for(int i = 0; i < 1000 ; i++){
        n.append(intObj(i));
    }

    myTest m;
    int sum = m.getSum(n);
    return a.exec();
}


int myTest::getSum(QList<intObj> numbers){
    auto sum = QtConcurrent::mappedReduced(numbers,mapFunction,reduceFunction);
    return sum.result().val();
}

This program now runs correctly but the map and reduce functions are outside the class. How can I modify this program such that map and reduce functions are in class intObj?

I would really appreciate a working example. Thanks in advance.

Upvotes: 1

Views: 348

Answers (2)

Mafura
Mafura

Reputation: 23

After a little more digging and rereading the Qtconcurrency on using member functions I realised that there are 2 major points

  1. The class of the container and the member functions SHOULD be the same
  2. In order to avoid head aches with passing this parameter, make the member functions static

Here is the final working version

#include <QCoreApplication>
#include <QtConcurrent>
#include <functional>

class intObj{
    int m_value;
public:
    intObj(int val = 0):m_value(val){}

    int val() const {return m_value;}

    static intObj mapFunction(const intObj &num){
        return intObj(num.val());
    }

    static void reduceFunction(intObj &sum, const intObj &term){
        int x = sum.val();
        int y = term.val();
        sum = intObj(x+y);
    }

};

class myTest{
    public:
    int getSum(QList<intObj> numbers);

};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QList<intObj> n;

    for(int i = 0; i < 1000 ; i++){
        n.append(intObj(i));
    }

    myTest m;
    int sum = m.getSum(n);
    return a.exec();
}


int myTest::getSum(QList<intObj> numbers){
    auto sum = QtConcurrent::mappedReduced(numbers,&intObj::mapFunction,&intObj::reduceFunction);
    return sum.result().val();
}

Any suggestions on how to improve this program are most welcome.

Upvotes: 0

Holt
Holt

Reputation: 37616

You cannot pass pointer to method to mappedReduced like that.

  • If you don't need the object inside the MapFunction and ReduceFunction, you should make the two functions static:
static int mappedFunction(const int num){
    return num;
}

static void reduce(int &sum, const int term){
    sum += term;
}
auto sum = QtConcurrent::mappedReduced(numbers,
    std::bind(&myTest::mappedFunction, this, std::placeholders::_1),
    std::bind(&myTest::reduce, this, std::placeholders::_1, std::placeholders::_2));

// Or lambda if Qt support them:
auto sum = QtConcurrent::mappedReduced(numbers, 
    [this] (int num) { mappedFunction(num); },
    [this] (int &sum, int num) { reduce(sum, num); });

You could also use Function Objects and store a reference to your current myTest instance.

Upvotes: 2

Related Questions