Ошибка QtConcurrent: ссылка на нестатический член

Я использую Qt 5.1 и QtQuick 2.0 на Mac с OS-X 10.8.4.

Мой графический интерфейс Qt-QML перестает отвечать на запросы, потому что я блокирую цикл обработки событий с помощью операций ввода-вывода файла. Обычный подход к решению этой проблемы заключается в использовании нескольких потоков, как обсуждалось ВОТ Уилл Бикфорд.

Для этого я пытаюсь использовать:

QtConcurrent::blockingMapped()

что может быть проще, чем использование явного объекта QFuture. Я читал Qt docs а также классные примеры и получил следующий работающий код (смоделированный после этого пример):

// NOTE: this all seems to work:
#include <QList>
#include <iostream>
#include "dataobject.h"#include <QtConcurrent/QtConcurrentMap>

DataObject load(const QString &file) {
std::cout << "File I/O in thread = " << QThread::currentThread() << std::endl;
return DataObject anObject(file);
}

int main(int argc, char *argv[])
{
...

// Create a list of filenames:
int count = 5;
QList<QString> allFiles;
for (int i = 0; i < count; i++) {
allFiles.append(QString("aFileName"));
}
std::cout << "# of files = " << allFiles.size() << std::endl;

QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles,load);
std::cout << "# of objects = " << allTheDataObjects.size() << std::endl;

...
}

а вот заголовок и файлы реализации для DataObject:

#include <QString>
class DataObject
{
public:
DataObject();
DataObject(QString filename);
QString theFileName;
};

#include "dataobject.h"
DataObject::DataObject() {
theFileName = QString("no file");
}
DataObject::DataObject(QString filename) {
theFileName = filename;
//...
// Do file I/O stuff (slow) ...
}

Это не очень реалистично, но служит простым наброском для иллюстрации проблемы, с которой я столкнулся ниже.

Проблема возникает, когда я пытаюсь инкапсулировать QtConcurrent :: blockingMapped () в дополнительный класс «datamodel.h»:

#include "dataobject.h"class DataModel
{
public:
DataModel();
void runConcurrent();
DataObject load(const QString& fileList);
};

#include "datamodel.h"#include <QtConcurrent/QtConcurrentMap>
#include <iostream>

DataModel::DataModel() {}
DataObject DataModel::load(const QString &file) {
std::cout << "File I/O in thread = " << QThread::currentThread() << std::endl;
return DataObject anObject(file);
}
void DataModel::runConcurrent() {
// Create a list of filenames:
int count = 5;
QList<QString> allFiles;
for (int i = 0; i < count; i++)
allFiles.append(QString("dummyFileName"));
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles, this->load);
std::cout << "# of objects = " << allTheDataObjects.size() << std::endl;
}

И затем main () становится (обратите внимание, что я также переместил метод load () в класс DataModel):

#include <QList>
#include <iostream>
#include "dataobject.h"#include "datamodel.h"#include <QtConcurrent/QtConcurrentMap>

int main(int argc, char *argv[])
{
...

DataModel theModel;
theModel.runConcurrent();

...
}

Но теперь есть ошибка компилятора:

datamodel.cpp: error: reference to non-static member function must be called:
QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles, this->load);

Я не смог исправить ошибку компилятора путем инициализации экземпляра DataObject или DataModel (чтобы была видна нестатическая функция-член) и не был уверен, что еще можно попробовать.

Далее я подозреваю, что это может быть связано с проблемой привязки «functor» при настройке аргументов QtConcurrent (у меня не установлено boost, поэтому я не использую повышение :: BIND) так я и пытался Предложение мата использования C ++ 11 лямбда-выражений путем замены:

this->load

с:

[this](const QString& file){load(file);}

давая код:

QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles,
[this](const QString& file){load(file);});

Теперь я больше не получаю нестатическую ошибку члена, но возникает новая ошибка (указывает на строку выше):

datamodel.cpp: error: expected expression:

Я действительно пробил эту кроличью нору, вероятно, это простая ошибка, но мне трудно разобраться с этим.

Может кто-нибудь помочь?

0

Решение

Видимо, вы не используете C ++ 11 с лямбда-выражениями. Так что используйте привязки из STL или Boost или создайте объект функции.

QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles,
std::bind1st(std::mem_fun(&DataModel::load), this));

Хорошо, выше решение не может работать со ссылками (знаю ошибку). Определите функтор (или используйте Boost :: bind):

class LoadDataModel /*: public std::unary_function<QString, DataObject>*/ {
public:
LoadDataModel(DataModel *p) : d(p) {}

DataObject operator()(const QString &s) const {
return d->load(s);
}
private:
DataModel *d;
}

QList<DataObject> allTheDataObjects = QtConcurrent::blockingMapped(allFiles, LoadDataModel(this));
0

Другие решения

Хорошо, получил это на работу.

В случае, если это может принести пользу тем, кто может не захотеть связываться с привязками или написать свой собственный «функтор» (подход ниже намного проще):

Начните с использования статического типа в файле datamodel.h для функции «load»:

static DataObject load(const QString& fileList);

Это работает, потому что статические функции класса C ++ могут быть вызваны без необходимости создания экземпляра объекта.

Затем в файле datamodel.cpp это так просто:

DataModel::load

дать:

QList<DataObject> allTheDataObjects =
QtConcurrent::blockingMapped(allFiles, DataModel::load);

Затем код работает, как ожидалось.

0

По вопросам рекламы [email protected]